BZOJ2679: [Usaco2012 Open]Balanced Cow Subsets

n<=20个数,求能分成两个和相同的子集的子集数。

枚举子集的子集,复杂度3^n,不可,考虑折半。在一种可行方案中,每个数的系数只会是0,-1,1,题目就是要求找和为0的两个子集拼起来,将其中一个子集取反就对应成两个值相同的方案。比如找到一个子集值为x,那么另一个子集的值应为-x,只要把-x这个子集的系数全部取反,就得到两个值相同的集合,对应一种方案。

这样转换方便折半搜索的合并过程。在合并时,枚举左边的集合,把该集合对应的状态加进数组里排序,预先把右边所有状态排序后,就可以线性时间内比较相同。若是没有转换,则需要找和为0的两个状态,麻烦!复杂度6^(n/2)。

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 //#include<iostream>
 6 using namespace std;
 7 
 8 int n,half;
 9 #define maxn 100011
10 int first[maxn],list[maxn],next[maxn],cntl=0;
11 struct Right
12 {
13     int v,S;
14     bool operator < (const Right &b) const {return v<b.v;}
15 }r[maxn];int cntr=0;
16 bool vis[1100011];
17 int a[23];
18 int tmp[maxn],lt=0;
19 void dfsl(int p,int v,int S)
20 {
21     if (p==half+1)
22     {
23         list[++cntl]=v;
24         next[cntl]=first[S];
25         first[S]=cntl;
26         return;
27     }
28     dfsl(p+1,v,S);
29     dfsl(p+1,v+a[p],S|(1<<(p-1)));
30     dfsl(p+1,v-a[p],S|(1<<(p-1)));
31 }
32 void dfsr(int p,int v,int S)
33 {
34     if (p==n+1)
35     {
36         r[++cntr].v=v;
37         r[cntr].S=S;
38         return;
39     }
40     dfsr(p+1,v,S);
41     dfsr(p+1,v+a[p],S|(1<<(p-1)));
42     dfsr(p+1,v-a[p],S|(1<<(p-1)));
43 }
44 int main()
45 {
46     scanf("%d",&n);half=n/2;
47     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
48     memset(first,0,sizeof(first));
49     dfsl(1,0,0);dfsr(half+1,0,0);
50     sort(r+1,r+1+cntr);
51     memset(vis,0,sizeof(vis));
52     for (int i=0;i<(1<<half);i++)
53     {
54         lt=0;
55         for (int j=first[i];j;j=next[j]) tmp[++lt]=list[j];
56         sort(tmp+1,tmp+1+lt);
57         int k=1;
58         for (int j=1;j<=cntr;j++)
59         {
60             while (k<=lt && tmp[k]<r[j].v) k++;
61             if (k==lt+1) break;
62             if (tmp[k]==r[j].v) vis[i|r[j].S]=1;
63         }
64     }
65     int ans=0;
66     for (int i=1;i<(1<<n);i++) if (vis[i]) ans++;
67     printf("%d\n",ans);
68     return 0;
69 }
View Code

注意不要把0算进去。。。。。。

posted @ 2017-08-12 10:30  Blue233333  阅读(287)  评论(0编辑  收藏  举报