[关闭]
@ysner 2018-10-16T08:53:05.000000Z 字数 1299 阅读 1684

[Usaco2012 Open]Balanced Cow Subsets

搜索 meet_in_the_middle


题面

个数,从中任意选出一些数,使这些数能分成和相等的两组。
求有多少种选数的方案。

解析

暴力应该是的。
一般来说,以内的搜索题目,用准没错。
于是存下前个数的种方案,再搜后面个数的方案并与前面匹配即可。

蒟蒻为什么会呢?因为它没想到可以维护这两组间的差值。

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<set>
  8. #include<map>
  9. #define ll long long
  10. #define re register
  11. #define il inline
  12. #define fp(i,a,b) for(re int i=a;i<=b;++i)
  13. #define fq(i,a,b) for(re int i=a;i>=b;--i)
  14. using namespace std;
  15. const int N=1e6+1e5;
  16. int n,a[30],m,ok[N],ans;
  17. map<int,int>M;
  18. set<int>S[60000];
  19. set<int>::iterator it;
  20. il ll gi()
  21. {
  22. re ll x=0,t=1;
  23. re char ch=getchar();
  24. while(ch!=-'-'&&(ch<'0'||ch>'9')) ch=getchar();
  25. if(ch=='-') t=-1,ch=getchar();
  26. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  27. return x*t;
  28. }
  29. il void dfs(re int x,re int tot,re int s)
  30. {
  31. if(x>n/2)
  32. {
  33. if(M.find(tot)==M.end()) M[tot]=++m;
  34. re int t=M[tot];
  35. S[t].insert(s);
  36. return;
  37. }
  38. dfs(x+1,tot,s);
  39. dfs(x+1,tot+a[x],s|(1<<x-1));
  40. dfs(x+1,tot-a[x],s|(1<<x-1));
  41. }
  42. il void DFS(re int x,re int tot,re int s)
  43. {
  44. if(x>n)
  45. {
  46. if(M.find(tot)==M.end()) return;
  47. re int t=M[tot];
  48. for(it=S[t].begin();it!=S[t].end();++it)
  49. ok[(*it)|s]=1;
  50. return;
  51. }
  52. DFS(x+1,tot,s);
  53. DFS(x+1,tot+a[x],s|(1<<x-1));
  54. DFS(x+1,tot-a[x],s|(1<<x-1));
  55. }
  56. int main()
  57. {
  58. n=gi();
  59. fp(i,1,n) a[i]=gi();
  60. dfs(1,0,0);DFS(n/2+1,0,0);
  61. fp(i,1,(1<<n)-1) ans+=ok[i];
  62. printf("%d\n",ans);
  63. return 0;
  64. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注