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 }