蓝桥杯2021年第十二届省赛真题-砝码称重 - C语言网 (dotcpp.com)
题目描述
你有一架天平和 N 个砝码,这 N 个砝码重量依次是 W1, W2, · · · , WN。
请你计算一共可以称出多少种不同的重量?
注意砝码可以放在天平两边。
分析
可以使用DP将dp[i][j]表示只从前i个物品中选,且总重量为j的方案的集合,其属性是是否选用(bool)
一共有三种方案
方案一:不选第i个物品
方案二:将第i个物品加上(将第i个物品放在右边)
方案三:将第i个物品减去(将第i个物品减去)
注:为了防止减去第i个物品数组的标号为负数,需要加上一个值,使之始终为正数
cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 110, M = 200010, b = M / 2;
int n, m, ans, w[N], dp[N][M];
int main()
{
cin >> n;
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];
}
}
for(int i = 1; i <= m; i ++)
{
if(dp[n][i + b] == 1)ans ++;
}
cout << ans;
return 0;
}