[HAOI2013] 开关控制
Posted qjs12
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HAOI2013] 开关控制相关的知识,希望对你有一定的参考价值。
这题让我知道了一种从来没接触过的酷算法——折半搜索!
还让我知道了一个大佬——GTH!
还是一个省的,NOIP D1 T1 爆零都比我考的高......虽然我也只有5分,但我是没推出来,人家推出来了被评测坑了,不能比......
这年头,OI界这么多女装大佬,而真的女生又这么爷们er么......
真诚的祝福您进队!
说实话我不太清楚 O ( n! ) 能过多大的数据。
首先这题的二进制表示状态也帅的不行,对于我这种位运算渣渣来说,能对着一份状压DP的代码膜...好久......然后陷入深深的绝望。
回正题。
所谓折半搜索,即把原来的搜索规模缩小一半,先搜索所给数据的前半部分,并用map将对应状态的值保存下来。
之后对后半部分数据进行搜索,搜索过程中查询当前状态的补集是否已经在第一次搜索中得到,没有的话就正常搜索,有的话就可以直接将两个状态的函数值直接相加得到一个答案,有效的减少了时间开销。
超大容量背包也是用的这个原理,不过我懒没做啊,而且COGS上没......
其实我的理解也只是皮毛,毕竟只这一道题,而且对时间复杂度以及正确性也存在一定的疑问。
不过还是过了,好像正解是解方程组?我开始也试着推了推,不过并不会解。
真的不喜欢数学题啊,高斯消元寒假学完也忘得一干二净了。
。。。。。。
// q.c // mark~ #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<map> using namespace std; typedef long long LL; const int M=35+7; int n,m,mid; bool f[M][M]; LL aim,ans,w[M]; map<LL,LL> cost; void dfs1(int x,LL y,LL z) { if(y) if(z<cost[y]||!cost[y]) cost[y]=z; if(z>ans) return ; if(y==aim) { ans=min(ans,z); return ; } for(int i=x;i<=mid;i++) dfs1(i+1,y^w[i],z+1); } void dfs2(int x,LL y,LL z) { if(z>ans) return ; if(y==aim) { ans=min(ans,z); return ; } LL dy=aim-y; if(cost[dy]) { ans=min(ans,z+cost[dy]); return ; } for(int i=x;i<=n;i++) dfs2(i+1,y^w[i],z+1); } int main() { freopen("haoi13t3.in","r",stdin); freopen("haoi13t3.out","w",stdout); scanf("%d%d",&n,&m); aim=((long long)1<<n)-1; ans=n; mid=n/2; int a,b; for(int i=1;i<=m;i++) { scanf("%d%d",&a,&b); f[a][b]=f[b][a]=true; } for(int i=1;i<=n;i++) { f[i][i]=1; LL x=0; for(int j=1;j<=n;j++) if(f[i][j]) x|=(long long)1<<j-1; w[i]=x; } dfs1(1,0,0); dfs2(mid+1,0,0); printf("%lld\n",ans); return 0; }
以上是关于[HAOI2013] 开关控制的主要内容,如果未能解决你的问题,请参考以下文章