题目连接
集合:f [ i ][ j ] 代表前i个砝码是否可以称出j的重量
关于第n个砝码
- (1)第n个砝码不选
- (2)第n个砝码选,放左边 加w[n]
- (3)第n个砝码选,放右边 减w[n]
#include<iostream>
#include<cmath>
using namespace std;
const int N = 110, M = 200010, B = M / 2;//B为偏移量,将j=-m移动到正整数范围
int n,m,w[N];
bool f[N][M];
int main(){
cin>>n;
for(int i=1; i<=n; i++) cin>>w[i], m+=w[i];//m计算最大能秤出的重量
f[0][B] = true;
for(int i=1; i<=n; i++){ //查找前i个物品中能中能秤出的重量
for(int j=-m; j<=m; j++){ //从最小重量到最大重量依次枚举
//不选i能秤出j的重量
f[i][j+B] = f[i-1][j+B];
//选i能秤出j的重量,则1~i-1中必能选出能秤出j-w[i]重量的
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 i=1; i<=m; i++) if(f[n][i+B]) res++;
cout<<res<<endl;
return 0;
}