哪里有什么不可言会的嘛。。。
考虑原本的操作数为n+m(将所有面积放到一个奇怪的地方去,从那个奇怪的地方取面积)。
然而有些子集的和是相等的,这样这些子集就并不用放到那个奇怪的地方去。也不用取出来。少2次操作。
dp[s]表示最多从这个集合里分出多少个子集,使得a,b对应子集和相等。(表示本来要dp[s][t]的。。。一个意思了。。。)
然后转移。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,sum[1<<21],f[1<<21]; int lowbit(int x) { return (x&(-x)); } int main() { scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",&sum[1<<i]); scanf("%d",&m);for (int i=1;i<=m;i++) {scanf("%d",&sum[1<<(n+i)]);sum[1<<(n+i)]=-sum[1<<(n+i)];} n+=m; int top=1<<n; for (int i=1;i<top;i++) { sum[i]=sum[lowbit(i)]+sum[i-lowbit(i)]; for (int j=1;j<=n;j++) { if (i&(1<<j)) f[i]=max(f[i],f[i-(1<<j)]); } f[i]+=(sum[i]==0); } printf("%d\n",n-2*f[top-1]); return 0; }