砝码称重 (背包问题,做2次)(蓝桥杯)
思路:
首先正向的把能够组合在一起的数弄出来(直接加的那种,背包)
对于减法, 就利用之前弄出来的数作为初始值,选出一些数来减到掉就可以了(背包的思想),(相同的砝码出现在左右2边会被约掉的,所以没关系)

#include <bits/stdc++.h> using namespace std; #define ri register int #define M 100005 template <class G> void read(G &x) { x=0;int f=0; char ch=getchar(); while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x=f?-x:x; return ; } bool f[M]; int n,val[M]; int m; int main(){ read(n); for(ri i=1;i<=n;i++) { read(val[i]);m+=val[i]; } f[0]=1; for(ri i=1;i<=n;i++) { for(ri j=m;j>=val[i];j--) { if(f[j-val[i]]) f[j]=1; } } for(ri i=1;i<=n;i++) { for(ri j=val[i];j<=m;j++) { if(f[j]) f[j-val[i]]=1; } } long long ans=0; for(ri i=1;i<=m;i++) { if(f[i]) ans++; } printf("%lld",ans); return 0; }