标签:开始 数学 mes space ring 搜索 scan freopen pre
这题让我知道了一种从来没接触过的酷算法——折半搜索!
还让我知道了一个大佬——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;
}
标签:开始 数学 mes space ring 搜索 scan freopen pre
原文地址:https://www.cnblogs.com/qjs12/p/8848892.html