HDU-1964 Pipes 插头DP

  题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1964

  空白区域之间有权值,求经过所有空白区域的哈密顿回路的最小权值。简单的插头DP,空白区域特殊处理即可。

  1 //STATUS:C++_AC_203MS_664KB
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 #include<math.h>
  6 #include<iostream>
  7 #include<string>
  8 #include<algorithm>
  9 #include<vector>
 10 #include<queue>
 11 #include<stack>
 12 #include<map>
 13 using namespace std;
 14 #define LL long long
 15 #define pii pair<int,int>
 16 #define Max(a,b) ((a)>(b)?(a):(b))
 17 #define Min(a,b) ((a)<(b)?(a):(b))
 18 #define mem(a,b) memset(a,b,sizeof(a))
 19 #define lson l,mid,rt<<1
 20 #define rson mid+1,r,rt<<1|1
 21 const int N=21,INF=0x3f3f3f3f,MOD=40001,STA=8000010;
 22 const double DNF=1e13;
 23 
 24 int g[N][N],code[N],ma[N];
 25 int T,n,m,ex,ey;
 26 
 27 struct Hash{     //Hash表,MOD为表长,STA为表大小
 28     int first[MOD],next[STA],size;
 29     int f[STA];
 30     LL sta[STA];
 31     void init(){
 32         size=0;
 33         mem(first,-1);
 34     }
 35     void add(LL st,int ans){
 36         int i,u=st%MOD;
 37         for(i=first[u];i!=-1;i=next[i]){
 38             if(sta[i]==st){
 39                 f[i]=Min(f[i],ans);
 40                 return;
 41             }
 42         }
 43         sta[size]=st;
 44         f[size]=ans;
 45         next[size]=first[u];
 46         first[u]=size++;
 47     }
 48 }hs[2];
 49 
 50 void shift(int p)    //换行移位
 51 {
 52     int k;
 53     LL sta;
 54     for(k=0;k<hs[!p].size;k++){
 55         sta=hs[!p].sta[k]<<3;
 56         hs[p].add(sta,hs[!p].f[k]);
 57     }
 58 }
 59 
 60 LL getsta()   //最小表示法
 61 {
 62     LL i,cnt=1,sta=0;
 63     mem(ma,-1);
 64     ma[0]=0;
 65     for(i=0;i<=m;i++){
 66         if(ma[code[i]]==-1)ma[code[i]]=cnt++;
 67         code[i]=ma[code[i]];
 68         sta|=(LL)code[i]<<(3*i);
 69     }
 70     return sta;
 71 }
 72 
 73 void getcode(LL sta)
 74 {
 75     int i;
 76     for(i=0;i<=m;i++){
 77         code[i]=sta&7;
 78         sta>>=3;
 79     }
 80 }
 81 
 82 void unblock(int i,int j,int p)
 83 {
 84     int k,t;
 85     LL cnt,x,y;
 86     for(k=0;k<hs[!p].size;k++){
 87         getcode(hs[!p].sta[k]);
 88         x=code[j],y=code[j+1];
 89         cnt=hs[!p].f[k];
 90         if(x && y){     //合并连通分量
 91             code[j]=code[j+1]=0;
 92             if(x!=y){
 93                 for(t=0;t<=m;t++)
 94                     if(code[t]==y)code[t]=x;
 95                 hs[p].add(getsta(),cnt+(g[i][j]<10?g[i][j]:0));
 96             }
 97             else if(i==ex && j==ey){   //最后一个点特殊处理
 98                 hs[p].add(getsta(),cnt);
 99             }
100         }
101         else if(x&&!y || !x&&y){   //延续连通分量
102             t=x?x:y;
103             if(g[i+1][j]>=0){
104                 code[j]=t;code[j+1]=0;
105                 hs[p].add(getsta(),cnt+(g[i][j]<10?g[i][j]:0));
106             }
107             if(g[i][j+1]>=0){
108                 code[j]=0;code[j+1]=t;
109                 hs[p].add(getsta(),cnt+(g[i][j]<10?g[i][j]:0));
110             }
111         }
112         else {  //创建新连通分量
113             if(g[i][j]>=0 && g[i][j]<=9){
114                 hs[p].add(getsta(),cnt);
115             }
116             if(g[i+1][j]>=0 && g[i][j+1]>=0){
117                 code[j]=code[j+1]=8;
118                 hs[p].add(getsta(),cnt);
119             }
120         }
121     }
122 }
123 
124 void block(LL j,int p)
125 {
126     int k;
127     for(k=0;k<hs[!p].size;k++){
128         getcode(hs[!p].sta[k]);
129         if(code[j]==0 && code[j+1]==0)
130             hs[p].add(getsta(),hs[!p].f[k]);
131     }
132 }
133 
134 int slove()
135 {
136     int i,j,p;
137     hs[0].init();
138     hs[p=1].init();
139     hs[0].add(0,0);
140     for(i=0;i<n;i++){
141         for(j=0;j<m;j++){
142             if(g[i][j]>=0)unblock(i,j,p);
143             else p=!p;
144             hs[p=!p].init();
145         }
146         shift(p);   //换行移位
147         hs[p=!p].init();
148     }
149     for(i=0;i<hs[!p].size;i++)
150         if(hs[!p].sta[i]==0)return hs[!p].f[i];
151     return 0;
152 }
153 
154 int main()
155 {
156  //   freopen("in.txt","r",stdin);
157     int i,j,ans;
158     char s[N];
159     scanf("%d",&T);
160     while(T--)
161     {
162         scanf("%d%d",&n,&m);
163         mem(g,-1);
164         n=n*2-1;
165         m=m*2-1;
166         scanf("%s",s);
167         getchar();
168         for(i=0;i<n;i++){
169             gets(s);
170             for(j=1;j<=m;j++){
171                 if(s[j]==' ')g[i][j-1]=10;
172                 else if(s[j]=='#')g[i][j-1]=-1;
173                 else g[i][j-1]=s[j]-'0';
174             }
175         }
176         scanf("%s",s);
177         ex=n-1,ey=m-1;
178 
179         ans=slove();
180 
181         printf("%d\n",ans);
182     }
183     return 0;
184 }

 

posted @ 2013-04-07 13:02  zhsl  阅读(297)  评论(0编辑  收藏  举报