开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第34天,点击查看活动详情
[蓝桥杯 2021 省 AB] 砝码称重
题目描述
你有一架天平和 个砝码, 这 个砝码重量依次是 。 请你计算一共可以称出多少种不同的重量?
注意砝码可以放在天平两边。
输入格式
输入的第一行包含一个整数 。
第二行包含 个整数: 。
输出格式
输出一个整数代表答案。
样例 #1
样例输入 #1
3
1 4 6
样例输出 #1
10
提示
【样例说明】
能称出的 10 种重量是: 。
【评测用例规模与约定】
对于 的评测用例, 。
对于所有评测用例, 个砝码总重不超过 。
蓝桥杯 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;
}