bzoj1814: Ural 1519 Formula 1 动态规划 插头dp
http://acm.timus.ru/problem.aspx?space=1&num=1519
题目描述
一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数。
输入
The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (full stop) means a cell, where a segment of the race circuit should be built, and character "*" (asterisk) - a cell, where a gopher hole is located.
输出
You should output the desired number of ways. It is guaranteed, that it does not exceed 2^63-1.
样例输入
4 4
**..
....
....
....样例输出
2
直接写时间复杂度过不了,直接写了个dp里面有很多无用状态,剪枝一下(存下一个的有用状态)就行了。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 using namespace std; 8 #define LL long long 9 int n,m; 10 char ch[15][15]={}; 11 int id[15][15]={}; 12 LL shu[15]={}; 13 map< int,LL >f[200]; 14 inline int getit(int z,int i){return (z/shu[i])%3;} 15 int main(){ 16 scanf("%d%d",&n,&m); 17 for(int i=1;i<=n;i++)scanf("%s",ch[i]+1); 18 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)id[i][j]=(i-1)*m+j; 19 shu[1]=1;int ff=0; 20 for(int i=2;i<=m+1;i++)shu[i]=shu[i-1]*3; 21 if(ch[1][1]=='.'){f[1][1+2*3]=1;ff=1;} 22 else f[1][0]=1; 23 int mx=shu[m+1]*3,now,nex,fla,z,x,y; LL val; 24 for(int i=1;i<=n;i++){ 25 for(int j=1;j<m;j++){ 26 if(i==n&&j==m-1)break; 27 now=id[i][j];nex=now+1;fla=0; 28 if(ch[i][j+1]!='.')fla=1; 29 if(ch[i][j]==1)ff=1; 30 for(int w=ff;w<mx;w++){ 31 val=f[now][w]; 32 if(val==0)continue; 33 x=getit(w,j+1);y=getit(w,j+2); 34 if(fla){ 35 if(x==0&&y==0){ 36 z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2]; 37 f[nex][z]+=val; 38 } 39 continue; 40 } 41 if(x==0&&y==0){ 42 z=w+(1-x)*shu[j+1]+(2-y)*shu[j+2]; 43 f[nex][z]+=val; 44 } 45 else if(x==0||y==0){ 46 z=w+(x+y-x)*shu[j+1]+(0-y)*shu[j+2]; 47 f[nex][z]+=val; 48 z=w+(0-x)*shu[j+1]+(x+y-y)*shu[j+2]; 49 f[nex][z]+=val; 50 } 51 else if(x==y){ 52 z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2]; 53 int zz,zzz; 54 if(x==1){ 55 zz=-1;zzz=j+2; 56 while(zz!=0){ 57 ++zzz; 58 if(zzz>m+1)break; 59 if(getit(w,zzz)==1)--zz; 60 if(getit(w,zzz)==2) ++zz; 61 } 62 if(zz!=0)continue; 63 z=z+(1-2)*shu[zzz]; 64 } 65 else{ 66 zz=1;zzz=j+1; 67 while(zz!=0){ 68 --zzz; 69 if(zzz>m+1)break; 70 if(getit(w,zzz)==1)--zz; 71 if(getit(w,zzz)==2) ++zz; 72 } 73 if(zz!=0)continue; 74 z=z+(2-1)*shu[zzz]; 75 } 76 f[nex][z]+=val; 77 } 78 else if(x==2&&y==1){ 79 z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2]; 80 f[nex][z]+=val; 81 } 82 } 83 } 84 if(i==n)break; 85 now=i*m;nex=now+1; 86 fla=0; 87 if(ch[i+1][1]!='.')fla=1; 88 if(ch[i][m]=='.')ff=1; 89 for(int w=ff;w<mx;++w){ 90 val=f[now][w]; 91 if(val==0)continue; 92 if(getit(w,m+1)!=0)continue; 93 x=getit(w,1); 94 if(fla){ 95 if(!x){ 96 z=(w%shu[m+1]-x)*3; f[nex][z]+=val; 97 } 98 continue; 99 } 100 if(x==1){ 101 z=(w%shu[m+1]-x)*3; 102 z=z+1;f[nex][z]+=val; 103 z=z+2;f[nex][z]+=val; 104 } 105 else if(x==0){ 106 z=(w%shu[m+1]-x)*3+1+2*3; 107 f[nex][z]+=val; 108 } 109 } 110 } 111 printf("%lld\n",f[n*m-1][shu[m]*1+shu[m+1]*2]); 112 return 0; 113 }
更改之后不开O2跑12*12的无障碍图需要快2s,大概是用map复杂度加了个log的锅……不想写hash……
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 using namespace std; 8 #define LL long long 9 int n,m; 10 char ch[15][15]={}; 11 int id[15][15]={}; 12 int cun[2][400010]={},tot[2]={}; 13 LL shu[15]={}; 14 map< int,LL >f[200]; 15 inline int getit(int z,int i){return (z/shu[i])%3;} 16 int main(){ 17 scanf("%d%d",&n,&m); 18 for(int i=1;i<=n;i++)scanf("%s",ch[i]+1); 19 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)id[i][j]=(i-1)*m+j; 20 shu[1]=1; 21 for(int i=2;i<=m+1;i++)shu[i]=shu[i-1]*3; 22 if(ch[1][1]=='.'){f[1][1+2*3]=1;tot[1]=1;cun[1][1]=1+2*3;} 23 else { f[1][0]=1;tot[1]=1;cun[1][1]=0;} 24 int now,nex,fla,z,x,y,id1,id2; LL val; 25 for(int i=1;i<=n;i++){ 26 for(int j=1;j<m;j++){ 27 if(i==n&&j==m-1)break; 28 now=id[i][j];nex=now+1;fla=0; 29 if(ch[i][j+1]!='.')fla=1; 30 id1=id[i][j]&1;id2=id1^1; 31 tot[id2]=0; 32 for(int k=1;k<=tot[id1];k++){ 33 int w=cun[id1][k]; 34 val=f[now][w]; 35 if(val==0)continue; 36 x=getit(w,j+1);y=getit(w,j+2); 37 if(fla){ 38 if(x==0&&y==0){ 39 z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2]; 40 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 41 f[nex][z]+=val; 42 } 43 continue; 44 } 45 if(x==0&&y==0){ 46 z=w+(1-x)*shu[j+1]+(2-y)*shu[j+2]; 47 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 48 f[nex][z]+=val; 49 } 50 else if(x==0||y==0){ 51 z=w+(x+y-x)*shu[j+1]+(0-y)*shu[j+2]; 52 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 53 f[nex][z]+=val; 54 z=w+(0-x)*shu[j+1]+(x+y-y)*shu[j+2]; 55 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 56 f[nex][z]+=val; 57 } 58 else if(x==y){ 59 z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2]; 60 int zz,zzz; 61 if(x==1){ 62 zz=-1;zzz=j+2; 63 while(zz!=0){ 64 ++zzz; 65 if(zzz>m+1)break; 66 if(getit(w,zzz)==1)--zz; 67 if(getit(w,zzz)==2) ++zz; 68 } 69 if(zz!=0)continue; 70 z=z+(1-2)*shu[zzz]; 71 } 72 else{ 73 zz=1;zzz=j+1; 74 while(zz!=0){ 75 --zzz; 76 if(zzz>m+1)break; 77 if(getit(w,zzz)==1)--zz; 78 if(getit(w,zzz)==2) ++zz; 79 } 80 if(zz!=0)continue; 81 z=z+(2-1)*shu[zzz]; 82 } 83 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 84 f[nex][z]+=val; 85 } 86 else if(x==2&&y==1){ 87 z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2]; 88 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 89 f[nex][z]+=val; 90 } 91 } 92 } 93 if(i==n)break; 94 now=i*m;nex=now+1; 95 fla=0; 96 if(ch[i+1][1]!='.')fla=1; 97 id1=id[i][m]&1;id2=id1^1; 98 tot[id2]=0; 99 for(int k=1;k<=tot[id1];++k){ 100 int w=cun[id1][k]; 101 val=f[now][w]; 102 if(val==0)continue; 103 if(getit(w,m+1)!=0)continue; 104 x=getit(w,1); 105 if(fla){ 106 if(!x){ 107 z=(w%shu[m+1]-x)*3; 108 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 109 f[nex][z]+=val; 110 } 111 continue; 112 } 113 if(x==1){ 114 z=(w%shu[m+1]-x)*3; 115 z=z+1; if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 116 f[nex][z]+=val; 117 z=z+2; if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 118 f[nex][z]+=val; 119 } 120 else if(x==0){ 121 z=(w%shu[m+1]-x)*3+1+2*3; 122 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 123 f[nex][z]+=val; 124 } 125 } 126 } 127 printf("%lld\n",f[n*m-1][shu[m]*1+shu[m+1]*2]); 128 return 0; 129 }
用map竟然过了……不过要注意一下最后输出的是最后一个可行位置的答案,很有可能最后一个点不是可行的,被坑了一下QAQ
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 using namespace std; 8 #define LL long long 9 int n,m; 10 char ch[15][15]={}; 11 int id[15][15]={}; 12 int cun[2][400010]={},tot[2]={}; 13 LL shu[15]={}; 14 map< int,LL >f[200]; 15 inline int getit(int z,int i){return (z/shu[i])%3;} 16 int main(){ 17 scanf("%d%d",&n,&m); 18 for(int i=1;i<=n;i++)scanf("%s",ch[i]+1); 19 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)id[i][j]=(i-1)*m+j; 20 int idx=0,idy=0; 21 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(ch[i][j]=='.'){idx=i;idy=j;} 22 if(idy<=1){printf("0\n");return 0;} 23 shu[1]=1; 24 for(int i=2;i<=m+1;i++)shu[i]=shu[i-1]*3; 25 if(ch[1][1]=='.'){f[1][1+2*3]=1;tot[1]=1;cun[1][1]=1+2*3;} 26 else { f[1][0]=1;tot[1]=1;cun[1][1]=0;} 27 int now,nex,fla,z,x,y,id1,id2; LL val; 28 for(int i=1;i<=idx;i++){ 29 for(int j=1;j<m;j++){ 30 if(i==n&&j==m-1)break; 31 now=id[i][j];nex=now+1;fla=0; 32 if(ch[i][j+1]!='.')fla=1; 33 id1=id[i][j]&1;id2=id1^1; 34 tot[id2]=0; 35 for(int k=1;k<=tot[id1];k++){ 36 int w=cun[id1][k]; 37 val=f[now][w]; 38 if(val==0)continue; 39 x=getit(w,j+1);y=getit(w,j+2); 40 if(fla){ 41 if(x==0&&y==0){ 42 z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2]; 43 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 44 f[nex][z]+=val; 45 } 46 continue; 47 } 48 if(x==0&&y==0){ 49 z=w+(1-x)*shu[j+1]+(2-y)*shu[j+2]; 50 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 51 f[nex][z]+=val; 52 } 53 else if(x==0||y==0){ 54 z=w+(x+y-x)*shu[j+1]+(0-y)*shu[j+2]; 55 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 56 f[nex][z]+=val; 57 z=w+(0-x)*shu[j+1]+(x+y-y)*shu[j+2]; 58 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 59 f[nex][z]+=val; 60 } 61 else if(x==y){ 62 z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2]; 63 int zz,zzz; 64 if(x==1){ 65 zz=-1;zzz=j+2; 66 while(zz!=0){ 67 ++zzz; 68 if(zzz>m+1)break; 69 if(getit(w,zzz)==1)--zz; 70 if(getit(w,zzz)==2) ++zz; 71 } 72 if(zz!=0)continue; 73 z=z+(1-2)*shu[zzz]; 74 } 75 else{ 76 zz=1;zzz=j+1; 77 while(zz!=0){ 78 --zzz; 79 if(zzz>m+1)break; 80 if(getit(w,zzz)==1)--zz; 81 if(getit(w,zzz)==2) ++zz; 82 } 83 if(zz!=0)continue; 84 z=z+(2-1)*shu[zzz]; 85 } 86 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 87 f[nex][z]+=val; 88 } 89 else if(x==2&&y==1){ 90 z=w+(0-x)*shu[j+1]+(0-y)*shu[j+2]; 91 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 92 f[nex][z]+=val; 93 } 94 } 95 } 96 if(i==n)break; 97 now=i*m;nex=now+1; 98 fla=0; 99 if(ch[i+1][1]!='.')fla=1; 100 id1=id[i][m]&1;id2=id1^1; 101 tot[id2]=0; 102 for(int k=1;k<=tot[id1];++k){ 103 int w=cun[id1][k]; 104 val=f[now][w]; 105 if(val==0)continue; 106 if(getit(w,m+1)!=0)continue; 107 x=getit(w,1); 108 if(fla){ 109 if(!x){ 110 z=(w%shu[m+1]-x)*3; 111 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 112 f[nex][z]+=val; 113 } 114 continue; 115 } 116 if(x==1){ 117 z=(w%shu[m+1]-x)*3; 118 z=z+1; if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 119 f[nex][z]+=val; 120 z=z+2; if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 121 f[nex][z]+=val; 122 } 123 else if(x==0){ 124 z=(w%shu[m+1]-x)*3+1+2*3; 125 if(f[nex][z]==0)cun[id2][++tot[id2]]=z; 126 f[nex][z]+=val; 127 } 128 } 129 } 130 printf("%lld\n",f[(idx-1)*m+idy-1][shu[idy]*1+shu[idy+1]*2]); 131 return 0; 132 }
cnblog什么毛病啊……给代码加了标题如果要复制代码标题就到代码末尾了……mdzz