• BZOJ2679 : [Usaco2012 Open]Balanced Cow Subsets


    考虑折半搜索,每个数的系数只能是-1,0,1之中的一个,因此可以先通过$O(3^frac{n}{2})$的搜索分别搜索出两边每个状态的和以及数字的选择情况。

    然后将后一半的状态按照和排序,$O(2^frac{n}{2})$枚举前一半的每一个选择情况的状态,将该选择情况下所有状态按和排序,然后通过双指针求出所有合法状态。

    时间复杂度$O(6^frac{n}{2})$。

    #include<cstdio>
    #include<algorithm>
    const int N=20,M=1<<10,E=59100;
    int n,n0,i,j,k,a[N],g[M],v[E],nxt[E],ed,m,q[M],ce,ans;bool vis[1<<N];
    struct P{int s,S;}e[E];
    inline bool cmp(const P&a,const P&b){return a.s<b.s;}
    void dfsl(int x,int s,int S){
      if(x==n0){v[++ed]=s;nxt[ed]=g[S];g[S]=ed;return;}
      dfsl(x+1,s,S);
      dfsl(x+1,s+a[x],S|(1<<x));
      dfsl(x+1,s-a[x],S|(1<<x));
    }
    void dfsr(int x,int s,int S){
      if(x==n){e[ce].s=s;e[ce++].S=S;return;}
      dfsr(x+1,s,S);
      dfsr(x+1,s+a[x],S|(1<<x));
      dfsr(x+1,s-a[x],S|(1<<x));
    }
    int main(){
      scanf("%d",&n);n0=(n+1)/2;
      for(i=0;i<n;i++)scanf("%d",&a[i]);
      dfsl(0,0,0),dfsr(n0,0,0);
      std::sort(e,e+ce,cmp);
      for(i=0;i<1<<n0;i++){
        for(m=0,j=g[i];j;j=nxt[j])q[m++]=v[j];
        std::sort(q,q+m);
        for(j=k=0;j<ce;j++){
          while(k<m&&q[k]<e[j].s)k++;
          if(k==m)break;
          if(q[k]==e[j].s)vis[i|e[j].S]=1;
        }
      }
      for(i=1;i<1<<n;i++)if(vis[i])ans++;
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    Spring 学习笔记
    Hello Spring(3)ConnectionUtility
    android ndk开发
    java udp 广播及socket通讯
    android 横向滚动屏幕实现(2)
    android 基于ftp远程文件管理
    android 软键盘的弹出问题总结
    android 滚动字幕
    android 基于apache ftp server
    android 设置壁纸几种方法
  • 原文地址:https://www.cnblogs.com/clrs97/p/5665220.html
Copyright © 2020-2023  润新知