您的位置:首页 > 其它

HDU4026 Unlock the Cell Phone [状态压缩DP]

2012-08-27 23:24 232 查看
  一开始看范围特别小就写搜索了。。。结果自己随便出了个4*4就过不了了。。

  其实就是状态压缩DP,求哈密顿回路要多少条,只是要注意判断两点是否可以划线就可以了。

  

#include <stdio.h>
#include <string.h>
#include <algorithm>
typedef __int64 LL;
int n,m,tot;
int mz[25],bet[25][25][25],full;
int zero[16],zeros,hzero[25],lowb[65536];
LL d[16][65536],ans;
int cant(int st,int en,int stat){
st=zero[st],en=zero[en];
if(st>en)std::swap(st,en);
for(int i=1;i<=bet[st][en][0];i++){
int x=bet[st][en][i];
if(mz[x]==1)return 1;
if(mz[x]==0&&((stat>>hzero[x])&1)==0)return 1;
}
return 0;
}
LL dp(int last,int stat){
if(d[last][stat]!=-1)return d[last][stat];
if(stat==(stat&-stat))return 1;
LL nans=0;
int nstat=stat,now,i;
while(nstat){
now=(nstat&-nstat),i=lowb[now],nstat-=now;;
if(i==last||cant(i,last,stat))continue;
nans+=dp(i,stat&~(1<<last));
}
return d[last][stat]=nans;
}
int between(int k,int i,int j,int n,int m){
int xk=k/m,yk=k%m,xi=i/m,yi=i%m,xj=j/m,yj=j%m;
if((xk-xi)*(xk-xj)<=0&&(yk-yi)*(yk-yj)<=0){
if((yj-yi)*(xk-xi)==(xj-xi)*(yk-yi))return 1;
}
return 0;
}
void init(int n,int m){
for(int i=0;i<tot;i++){
for(int j=i+1;j<tot;j++){
int &x=bet[i][j][0];x=0;
for(int k=i+1;k<j;k++){
if(between(k,i,j,n,m))x++,bet[i][j][x]=k;
}
}
}
for(int i=0,x=1;i<16;i++,x<<=1)lowb[x]=i;
}
int main(){
//  freopen("test.in","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF){
ans=0,tot=n*m,zeros=0;
init(n,m);
for(int i=0;i<tot;i++){
scanf("%d",&mz[i]);
if(mz[i]==0)hzero[i]=zeros,zero[zeros++]=i;
}
full=(1<<zeros)-1;
for(int i=0;i<zeros;i++)for(int j=0;j<=full;j++)d[i][j]=-1;
for(int i=0;i<zeros;i++)ans+=dp(i,full);
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: