POJ-3133 Manhattan Wiring 插头DP

  题目链接:http://poj.org/problem?id=3133

  用两条线段分别连接2-2和3-3,使得他们长度的总和最小。

  典型的插头DP题目,用0,2,3,种状态来表示每个格子的插头分别是没有插头,2号插头,3号插头,然后把所有可能的转移情况列出来,只是情况比较多,而且一定要考虑仔细,不然检查代码会很惨的。。话说A完这道题后感觉真爽啊O(∩_∩)O~

  1 //STATUS:C++_AC_360MS_900KB
  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=10,INF=0x3f3f3f3f,MOD=60007,STA=1000010;
 22 const LL LNF=0x3f3f3f3f3f3f3f3f;
 23 const double DNF=100000000000;
 24 
 25 int g[N][N];
 26 int n,m;
 27 
 28 struct Hash{
 29     int first[MOD],next[STA],size;
 30     int f[STA],sta[STA];
 31     void init(){
 32         size=0;
 33         mem(first,-1);
 34     }
 35     void add(int 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         f[size]=ans;
 44         sta[size]=st;
 45         next[size]=first[u];
 46         first[u]=size++;
 47     }
 48 }hs[2];
 49 
 50 void shift(int p)
 51 {
 52     int i,flag=(1<<((m+1)<<1))-1;
 53     for(i=0;i<hs[!p].size;i++){
 54         hs[p].add((hs[!p].sta[i]<<2)&flag,hs[!p].f[i]);
 55     }
 56 }
 57 
 58 int slove()
 59 {
 60     int i,j,k,x,y,left,up,p,sta,f;
 61     hs[0].init();
 62     hs[0].add(0,0);
 63     hs[p=1].init();
 64     for(i=0;i<n;i++){
 65         for(j=0;j<m;j++,hs[p=!p].init()){
 66             for(k=0;k<hs[!p].size;k++){
 67                 sta=hs[!p].sta[k];
 68                 f=hs[!p].f[k]+1;
 69                 x=(3<<(j<<1))&sta;
 70                 y=(3<<((j+1)<<1))&sta;
 71                 left=x>>(j<<1);
 72                 up=y>>((j+1)<<1);
 73                 if(g[i][j]){
 74                     if(g[i][j]==2){  //独立插头
 75                         if(left==2 && up==0){
 76                             hs[p].add(sta^x,f);
 77                         }
 78                         else if(left==0 && up==2){
 79                             hs[p].add(sta^y,f);
 80                         }
 81                         else if(left==0 && up==0){
 82                             if(g[i+1][j]==1 || g[i+1][j]==2)hs[p].add(sta|(2<<(j<<1)),f);
 83                             if(g[i][j+1]==1 || g[i][j+1]==2)hs[p].add(sta|(2<<((j+1)<<1)),f);
 84                         }
 85                     }
 86                     else if(g[i][j]==3){  //独立插头
 87                         if(left==3 && up==0){
 88                             hs[p].add(sta^x,f);
 89                         }
 90                         else if(left==0 && up==3){
 91                             hs[p].add(sta^y,f);
 92                         }
 93                         else if(left==0 && up==0){
 94                             if(g[i+1][j]==1 || g[i+1][j]==3)hs[p].add(sta|(3<<(j<<1)),f);
 95                             if(g[i][j+1]==1 || g[i][j+1]==3)hs[p].add(sta|(3<<((j+1)<<1)),f);
 96                         }
 97                     }
 98                     else {  //g[i][j]==1
 99                         if(left==up && left){
100                             hs[p].add(sta^x^y,f);
101                         }
102                         else if((left==2 && up==0) || (left==0 && up==2)){
103                             if(g[i+1][j])hs[p].add(sta^y|(2<<(j<<1)),f);
104                             if(g[i][j+1])hs[p].add(sta^x|(2<<((j+1)<<1)),f);
105                         }
106                         else if((left==3 && up==0) || (left==0 && up==3)){
107                             if(g[i+1][j])hs[p].add(sta^y|(3<<(j<<1)),f);
108                             if(g[i][j+1])hs[p].add(sta^x|(3<<((j+1)<<1)),f);
109                         }
110                         else if(left==0 && up==0){   //这里一定要考虑仔细
111                             if(g[i+1][j] && g[i][j+1]){
112                                 hs[p].add(sta|(2<<(j<<1))|(2<<((j+1)<<1)),f);
113                                 hs[p].add(sta|(3<<(j<<1))|(3<<((j+1)<<1)),f);
114                             }
115                             hs[p].add(sta,f-1);
116                         }
117                     }
118                 }
119                 else if(left==0 && up==0){
120                     hs[p].add(sta,f-1);
121                 }
122             }
123         }
124         shift(p);
125         hs[p=!p].init();
126     }
127     p=!p;
128     for(i=0;i<hs[p].size;i++){
129         if(hs[p].sta[i]==0)return hs[p].f[i]-2;
130     }
131     return 0;
132 }
133 
134 int main()
135 {
136  //   freopen("in.txt","r",stdin);
137     int i,j,ans;
138     while(~scanf("%d%d",&n,&m) && (n || m))
139     {
140         mem(g,0);
141         for(i=0;i<n;i++){
142             for(j=0;j<m;j++){
143                 scanf("%d",&g[i][j]);
144                 if(g[i][j]==0)g[i][j]=1;
145                 else if(g[i][j]==1)g[i][j]=0;
146             }
147         }
148 
149         ans=slove();
150 
151         printf("%d\n",ans);
152     }
153     return 0;
154 }

 

posted @ 2013-04-03 13:12  zhsl  阅读(354)  评论(0编辑  收藏  举报