蓝桥杯砝码称重

65 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第34天,点击查看活动详情

[蓝桥杯 2021 省 AB] 砝码称重

题目描述

你有一架天平和 NN 个砝码, 这 NN 个砝码重量依次是 W1,W2,,WNW_{1}, W_{2}, \cdots, W_{N} 。 请你计算一共可以称出多少种不同的重量?

注意砝码可以放在天平两边。

输入格式

输入的第一行包含一个整数 NN

第二行包含 NN 个整数: W1,W2,W3,,WNW_{1}, W_{2}, W_{3}, \cdots, W_{N}

输出格式

输出一个整数代表答案。

样例 #1

样例输入 #1

3
1 4 6

样例输出 #1

10

提示

【样例说明】

能称出的 10 种重量是: 1234567910111 、 2 、 3 、 4 、 5 、 6 、 7 、 9 、 10 、 11

1=12=64( 天平一边放 6, 另一边放 4) 3=414=45=616=67=1+69=4+6110=4+611=1+4+6\begin{aligned} &1=1 \\ &2=6-4(\text { 天平一边放 } 6, \text { 另一边放 4) } \\ &3=4-1 \\ &4=4 \\ &5=6-1 \\ &6=6 \\ &7=1+6 \\ &9=4+6-1 \\ &10=4+6 \\ &11=1+4+6 \end{aligned}

【评测用例规模与约定】

对于 50%50 \% 的评测用例, 1N151 \leq N \leq 15

对于所有评测用例, 1N100,N1 \leq N \leq 100, N 个砝码总重不超过 10510^5

蓝桥杯 2021 第一轮省赛 A 组 F 题(B 组 G 题)。

分析

今天这题就是很简单的一个dp,就是分三种情况,不选,选了放左边和选了放右边三种情况,然后就可以列出状态转移方程,当然最后要注意一点,就是要加个偏移量B,因为数组下标不能为负数。

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#define pb push_back
#define ll long long
using namespace std;
const int N=110,M=200020,B=M/2;
bool dp[N][M*2];
int n;
int w[N];
int cnt=0;
int main(){
	cin>>n;
	int m=0;
	for(int i=1;i<=n;i++){
		cin>>w[i];
		m+=w[i];
	}
	dp[0][B]=1; 
	for(int i=1;i<=n;i++){
		for(int j=-m;j<=m;j++){
			dp[i][j+B]=dp[i-1][j+B];
			if(j-w[i]>=-m) dp[i][j+B]|=dp[i-1][j-w[i]+B];
			if(j+w[i]<=m) dp[i][j+B]|=dp[i-1][j+w[i]+B];
		}
	}
	int res=0;
	for(int j=1;j<=m;j++){
		if(dp[n][j+B]) res++;
	}
	cout<<res<<endl;
}