题目
思路
初始化:
f
[
0
]
[
0
]
=
t
r
u
e
f[0][0]=true
f[0][0]=true从前0个物品中选,凑出重量为0,是可以的,所以非空
j
j
j遍历要从
−
m
-m
−m到
m
m
m,这两种情况是把砝码都放一边的极端情况。
因为第二维可能为负数,所以要在第二维加一个偏移量。
代码
#include<cstdio>
using namespace std;
const int N=110,M=2e5+10,B=M/2; //B是偏移量,B的绝对值要比m大才行,因为这样才能使-m+B>0
int n,m,w[N];
bool f[N][M];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&w[i]),m+=w[i];
f[0][0+B]=true; //初始状态
for(int i=1;i<=n;i++)
for(int j=-m;j<=m;j++) //判断的时候不用加偏移量,计算、存储的时候带偏移量
{
f[i][j+B]=f[i-1][j+B];
if(j-w[i]>=-m) f[i][j+B]|=f[i-1][j-w[i]+B];
if(j+w[i]<=m) f[i][j+B]|=f[i-1][j+w[i]+B];
}
int res=0;
for(int j=1;j<=M;j++) //因为凑出的重量0是不算的,所以从1开始遍历,一直遍历到M
if(f[n][j+B]) //为什么不是m?因为这里加了偏移量,有一半的值已经远远比m大了
res++;
printf("%d",res);
return 0;
}