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
",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
",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
");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
",f[(idx-1)*m+idy-1][shu[idy]*1+shu[idy+1]*2]);
131     return 0;
132 }
这绝对是最后一版了

cnblog什么毛病啊……给代码加了标题如果要复制代码标题就到代码末尾了……mdzz

原文地址:https://www.cnblogs.com/137shoebills/p/8994374.html