P3067 [USACO12OPEN]Balanced Cow Subsets G
P3067 [USACO12OPEN]Balanced Cow Subsets G
折半搜索。
发现数据范围很小,但是直接搜索不现实,于是考虑折半搜索。
折半搜索本质就是只搜一半然后把两个答案拼起来。
这里注意要二进制压缩状态来判断重复。
代码:
#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;char ch=getchar();bool f=false;
while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
const int N=2e6+5;
int n,n1,a[21],ans[N],s,tot;
vector<int> p[N];
map<int,int> b;
void dfs1(int x,int sum,int now){
if(x>n1){
if(b[sum]==0) b[sum]=++tot;
p[b[sum]].push_back(now);
return;
}
dfs1(x+1,sum+a[x],now|(1<<(x-1)));
dfs1(x+1,sum-a[x],now|(1<<(x-1)));
dfs1(x+1,sum,now);
}
void dfs2(int x,int sum,int now){
if(x>n){
int t=b[sum];
if(t!=0) for(int i=0;i<p[t].size();i++) ans[p[t][i]|now]=1;
return;
}
dfs2(x+1,sum+a[x],now|(1<<(x-1)));
dfs2(x+1,sum-a[x],now|(1<<(x-1)));
dfs2(x+1,sum,now);
}
int main(){
read(n);
n1=n/2;
for(int i=1;i<=n;i++) read(a[i]);
dfs1(1,0,0);
dfs2(n1+1,0,0);
for(int i=1;i<=(1<<n);i++) s+=ans[i];
write(s);
return 0;
}