题目链接:砝码称重
题解:
f[i][j]表示选择前i个砝码总重量为j是否可以得到
我们设定砝码放在左边为正,放在右边为负
对于枚举到当前这个砝码,我们有三种选择方案:
1. 不选。则当前状态与上一个状态方案相同,即f[i][j] = f[i-1][j]
2. 选择放在左边。则f[i][j] = f[i-1][j-w[i]]
3. 选择放在右边。则f[i][j] = f[i-1][j+w[i]]。因为放在右边为负的,当前状态为j则上一个状态应该为j+w[i]
在这里j-w[i]会出现负数的情况,但是下标不能为负。不难发现重量为负数的时候和重量为正数的时候应该是相同的,因为重量只能为正,所以计算时取绝对值即可
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110, M = 1e5 + 7;
int w[N];
bool f[N][M];
int main()
{
int n, m = 0; scanf("%d", &n);
for (int i = 1 ; i <= n; i ++ ) scanf("%d", &w[i]), m += w[i];
f[0][0] = true;
for (int i = 1 ; i <= n; i ++ )
{
for (int j = 0; j <= m; j ++ )
{
//或运算,有1则为1
f[i][j] = f[i - 1][j];
if (j + w[i] <= m) f[i][j] |= f[i - 1][j + w[i]];
f[i][j] |= f[i - 1][abs(j - w[i])];
}
}
int ans = 0;
for (int i = 1; i <= m; i ++ ) if (f[n][i]) ans ++;
printf("%d\n", ans);
return 0;
}