• 【BZOJ2679】[USACO2012 Open] Balanced Cow Subsets(Meet in Middle)


    点此看题面

    大致题意:(n)个数中选出若干个数(不能不选),问有多少种选数的方案,使得选出的数能被分为两个和相等的集合。

    前言

    一眼就想到了这个做法,感觉理论上应该很难卡,可复杂度还是不太会证。。。

    (Meet in Middle)

    比较显然,每个数有三种状态:不选、被分在第一个集合(加上权值)、被分在第二个集合(减去权值)。

    然后考虑折半搜索(即(Meet in Middle)),就可以在(O(3^{10}))的复杂度内分别搜出数列两部分各自的状态。而如果两个状态能够匹配,当且仅当两个状态的权值互为相反数。

    但若仅仅是这么搞,就会发现同一个集合因不同的划分方式被计算了多次。

    因此对于每个状态我们不仅要记下值的和,还要状压记下集合内元素的选择方式。

    然后我们枚举权值互为相反数的每一对状态(就是这里,我感觉如果同一权值有很多状态会不会被卡掉啊),判断这种集合方式是否被选择过,没选择过则标记选择,并将答案加(1)

    具体实现详见代码。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 20
    using namespace std;
    int n,t1,t2,a[N+5],vis[1<<N+1];
    struct data
    {
    	int v,s;I data(CI a=0,CI b=0):v(a),s(b){}
    	I bool operator < (Con data& o) Con {return v<o.v;}
    }s1[60000],s2[60000];
    I void dfs(CI l,CI r,CI v=0,CI s=0)//Meet in Middle
    {
    	if(l>r) return (void)(r^n?s1[++t1]=data(v,s):s2[++t2]=data(-v,s));//存下状态,注意第二种权值和取相反数(后来想想其实不用)
    	dfs(l+1,r,v,s),dfs(l+1,r,v+a[l],s|(1<<l-1)),dfs(l+1,r,v-a[l],s|(1<<l-1));//分三种状态
    }
    int main()
    {
    	RI i;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d",a+i);
    	dfs(1,n/2),dfs(n/2+1,n),sort(s1+1,s1+t1+1),sort(s2+1,s2+t2+1);//排序
    	RI ans=0,p,l,r;for(p=1,l=1;l<=t1;l=r+1)
    	{
    		r=l;W(r<=t1&&s1[l].v==s1[r+1].v) ++r;//同种权值一并处理
    		W(p<=t2&&s2[p].v<s1[l].v) ++p;W(p<=t2&&s2[p].v==s1[l].v)//找到对应的权值
    			{for(i=l;i<=r;++i) !vis[s1[i].s|s2[p].s]&&(vis[s1[i].s|s2[p].s]=1,++ans);++p;}//注意集合方式要不同
    	}return printf("%d",ans-1),0;//答案减1,因为全不选的情况会被计算在内
    }
    
  • 相关阅读:
    Java日志第8天 2020.7.13
    Java日志第7天 2020.7.12
    Java日志第6天 2020.7.11
    Java日志第5天 2020.7.10
    Java日志第4天 2020.7.9
    Java日志第3天 2020.7.8
    设计模式_23种设计模式_目录
    ICacheEntry中SlidingExpiration与AbsoluteExpirationRelativeToNow的区别
    MySql中的replace into
    结巴分词
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ2679.html
Copyright © 2020-2023  润新知