bzoj2679:[Usaco2012 Open]Balanced Cow Subsets

思路:折半搜索,每个数的状态只有三种:不选、选入集合A、选入集合B,然后就暴搜出其中一半,插入hash表,然后再暴搜另一半,在hash表里查找就好了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 25
 
int n;
int a[maxn],t[maxn];
bool v[1025][1025];
int ans;
 
struct hash_table{
    static const int mod=242354;
    int tot,now[mod],pre[1000000],son[1000000],val[1000000];
    void insert(int t,int x){
        int pos=(x%mod+mod)%mod;
        for (int p=now[pos];p;p=pre[p]) if (son[p]==t&&val[p]==x) return;
        son[++tot]=t,val[tot]=x,pre[tot]=now[pos],now[pos]=tot;
    }
    int find(int t,int x){
        int pos=(x%mod+mod)%mod,ans=0;
        for (int p=now[pos];p;p=pre[p])
            if (val[p]==x&&!v[son[p]][t]){v[son[p]][t]=1;ans++;}
        return ans;
    }
}H;
 
void dfs1(int x,int val){
    if (x>n/2){
        int tmp=0;for (int i=1;i<=n/2;i++) tmp=tmp<<1|t[i];
        H.insert(tmp,val);return;
    }
    t[x]=1;dfs1(x+1,val+a[x]);
    t[x]=0;dfs1(x+1,val);
    t[x]=1;dfs1(x+1,val-a[x]);
}
 
void dfs2(int x,int val){
    if (x>n){
        int tmp=0;for (int i=n/2+1;i<=n;i++) tmp=tmp<<1|t[i];
        ans+=H.find(tmp,val);
        return;
    }
    t[x]=1;dfs2(x+1,val+a[x]);
    t[x]=0;dfs2(x+1,val);
    t[x]=1;dfs2(x+1,val-a[x]);
}
 
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    dfs1(1,0),dfs2(n/2+1,0);
    printf("%d
",ans-1);
    return 0;
}
原文地址:https://www.cnblogs.com/DUXT/p/6007126.html