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;
} 
posted @ 2021-04-20 22:41  __Anchor  阅读(78)  评论(0编辑  收藏  举报