ZOJ 3213
1 /* 2 ZOJ 3213 3 4 好吧,看过那种括号表示法后,就崩溃了,实在受不了。情况复杂,写了两天,人也有点傻X了,只能放弃,转而用最小表示法。 5 最小表示法不难写: 6 7 1)首先,要承认路径上有格子不选的情况,于是,在00的情况下,可扩展,也可不选。 8 2)不能出现环,因而不能有L=U的情况出现。 9 3)以下是模版代码,类同是必然。但转而求路径数的时候,应当去掉不扩展的情况,同时,在IF(L|U)的情况下,亦不必考虑当前是否为最后一个格子, 10 只需按写的转移即可。 11 4)增加独立插头时,必须在总的独立插头数小于2的情况下进行。 12 13 注意:之所以不能出现两个插头,是因为,独立插头是单向的路径,不能进了又出。限制这个条件是非常有必要的。而在此处我本以为若限制了条件就得不出 14 最优解,而其实,因为存在不选的状态,限制了这个条件依然是可以有最优解的。 15 */ 16 #include<stdio.h> 17 #include<string.h> 18 #include<algorithm> 19 #include<iostream> 20 using namespace std; 21 22 const int MAXD=15; 23 const int HASH=10007; 24 const int STATE=1000010; 25 26 int N,M; 27 int maze[MAXD][MAXD]; 28 int code[MAXD]; 29 int ch[MAXD]; 30 int num; 31 int ans; 32 33 struct HASHMAP 34 { 35 int head[HASH],next[STATE],size; 36 int state[STATE],dp[STATE]; 37 void init() 38 { 39 size=0; 40 memset(head,-1,sizeof(head)); 41 } 42 void push(int st,int ans) 43 { 44 int i,h=st%HASH; 45 for(i=head[h];i!=-1;i=next[i]) 46 if(state[i]==st) 47 { 48 if(dp[i]<ans)dp[i]=ans; 49 return; 50 } 51 state[size]=st; 52 dp[size]=ans; 53 next[size]=head[h]; 54 head[h]=size++; 55 } 56 }hm[2]; 57 void decode(int *code,int m,int st) 58 { 59 num=st&7;//?????? 60 st>>=3; 61 for(int i=m;i>=0;i--) 62 { 63 code[i]=st&7; 64 st>>=3; 65 } 66 } 67 int encode(int *code,int m) 68 { 69 int cnt=1; 70 memset(ch,-1,sizeof(ch)); 71 ch[0]=0; 72 int st=0; 73 for(int i=0;i<=m;i++) 74 { 75 if(ch[code[i]]==-1)ch[code[i]]=cnt++; 76 code[i]=ch[code[i]]; 77 st<<=3; 78 st|=code[i]; 79 } 80 st<<=3; 81 st|=num; 82 return st; 83 } 84 void shift(int *code,int m) 85 { 86 for(int i=m;i>0;i--)code[i]=code[i-1]; 87 code[0]=0; 88 } 89 void dpblank(int i,int j,int cur) 90 { 91 int k,left,up; 92 for(k=0;k<hm[cur].size;k++) 93 { 94 decode(code,M,hm[cur].state[k]); 95 left=code[j-1]; 96 up=code[j]; 97 if(left&&up) 98 { 99 if(left!=up) 100 { 101 code[j-1]=code[j]=0; 102 for(int t=0;t<=M;t++) 103 if(code[t]==up) 104 code[t]=left; 105 if(j==M)shift(code,M); 106 hm[cur^1].push(encode(code,M),hm[cur].dp[k]+maze[i][j]); 107 } 108 } 109 else if(left||up) 110 { 111 int t; 112 if(left)t=left; 113 else t=up; 114 if(maze[i][j+1]) 115 { 116 code[j-1]=0; 117 code[j]=t; 118 hm[cur^1].push(encode(code,M),hm[cur].dp[k]+maze[i][j]); 119 } 120 if(maze[i+1][j]) 121 { 122 code[j-1]=t; 123 code[j]=0; 124 hm[cur^1].push(encode(code,j==M?M-1:M),hm[cur].dp[k]+maze[i][j]); 125 } 126 if(num<2) //封住一端,增加一个独立插头。 127 { 128 num++; 129 code[j-1]=code[j]=0; 130 hm[cur^1].push(encode(code,j==M?M-1:M),hm[cur].dp[k]+maze[i][j]); 131 } 132 } 133 else 134 { 135 code[j-1]=code[j]=0; //讨论简单路径,只需不讨论不选的情况就可以了。 136 hm[cur^1].push(encode(code,j==M?M-1:M),hm[cur].dp[k]); 137 if(maze[i][j+1]&&maze[i+1][j]) 138 { 139 code[j-1]=code[j]=13; 140 hm[cur^1].push(encode(code,M),hm[cur].dp[k]+maze[i][j]); 141 } 142 if(num<2) 143 { 144 num++; 145 if(maze[i][j+1]) 146 { 147 code[j]=13; 148 code[j-1]=0; 149 hm[cur^1].push(encode(code,M),hm[cur].dp[k]+maze[i][j]); 150 } 151 if(maze[i+1][j]) 152 { 153 code[j-1]=13; 154 code[j]=0; 155 hm[cur^1].push(encode(code,j==M?M-1:M),hm[cur].dp[k]+maze[i][j]); 156 } 157 } 158 } 159 } 160 } 161 void dpblock(int i,int j,int cur) 162 { 163 int k; 164 for(k=0;k<hm[cur].size;k++) 165 { 166 decode(code,M,hm[cur].state[k]);//?????!!! 167 code[j-1]=code[j]=0; 168 if(j==M)shift(code,M); 169 hm[cur^1].push(encode(code,M),hm[cur].dp[k]); 170 } 171 } 172 void init() 173 { 174 scanf("%d%d",&N,&M); 175 ans=0; 176 memset(maze,0,sizeof(maze));//??????? 177 for(int i=1;i<=N;i++) 178 for(int j=1;j<=M;j++) 179 { 180 scanf("%d",&maze[i][j]); 181 if(maze[i][j]>ans)ans=maze[i][j]; 182 } 183 } 184 void solve() 185 { 186 int i,j,cur=0; 187 hm[cur].init(); 188 hm[cur].push(0,0); 189 for(i=1;i<=N;i++) 190 for(int j=1;j<=M;j++) 191 { 192 hm[cur^1].init(); 193 if(maze[i][j])dpblank(i,j,cur); 194 else dpblock(i,j,cur); 195 cur^=1; 196 } 197 for(i=0;i<hm[cur].size;i++) 198 if(hm[cur].dp[i]>ans) 199 ans=hm[cur].dp[i]; 200 printf("%d\n",ans); 201 } 202 int main() 203 { 204 int T; 205 scanf("%d",&T); 206 while(T--) 207 { 208 init(); 209 solve(); 210 } 211 return 0; 212 }
更新代码,自写的。WA了N久,感觉有几个问题要注意一下:
应当初始化图为0;
记住在增加独立插头时,任何时候要考虑是否<2
1 #include <iostream> 2 #include <stdio.h> 3 #include <cstring> 4 using namespace std; 5 6 7 const int MAXD=12; 8 const int MAXL=20007; 9 const int MAXH=1000010; 10 int n,m; 11 int ans; int num; 12 int map[MAXD][MAXD]; 13 int code[MAXD]; int pos[MAXD],stac[MAXD]; 14 int tmp[MAXD]; 15 16 17 struct HASHMAP{ 18 int hash[MAXL],state[MAXH],next[MAXH]; 19 int f[MAXH]; 20 int size; 21 void init(){ 22 size=0; 23 memset(hash,-1,sizeof(hash)); 24 } 25 void push(int st,int anst) { 26 int h=st%MAXL; 27 for(int i=hash[h];i!=-1;i=next[i]){ 28 if(state[i]==st){ 29 if(f[i]<anst){ 30 f[i]=anst; 31 } 32 return ; 33 } 34 } 35 state[size]=st; 36 f[size]=anst; 37 next[size]=hash[h]; 38 hash[h]=size++; 39 } 40 }hm[2]; 41 42 void decode(int st){ 43 for(int i=m;i>=0;i--){ 44 int t=st&3; 45 code[i]=t; 46 st=st>>2; 47 } 48 } 49 50 int fd_r(int j){ 51 int top=-1; 52 for(int i=0;i<=m;i++){ 53 if(code[i]==0) continue; 54 else if(code[i]==1){ 55 ++top; 56 pos[top]=i; stac[top]=code[i]; 57 } 58 else if(code[i]==2){ 59 if(pos[top]==j) return i; 60 else top--; 61 } 62 } 63 } 64 int fd_l(int j){ 65 int top=-1; 66 for(int i=0;i<=m;i++){ 67 if(code[i]==0) continue; 68 else if(code[i]==1){ 69 ++top; 70 pos[top]=i; stac[top]=code[i]; 71 } 72 else if(code[i]==2){ 73 if(i==j) return pos[top]; 74 else top--; 75 } 76 } 77 } 78 79 80 void dpblank(int i,int j,int cur){ 81 int em;int tmpst; int ls,us,tts; 82 for(int e=0;e<hm[cur].size;e++){ 83 int st=hm[cur].state[e]; 84 num=st&3; 85 st>>=2; 86 decode(st); 87 int left=code[j-1],up=code[j]; 88 ls=(m-j+1)*2; us=(m-j)*2; 89 if(!left&&!up){ 90 tmpst=(st^(left<<ls))^(up<<us); 91 if(j==m) tmpst=tmpst>>2; 92 tmpst<<=2; 93 tmpst|=num; 94 hm[cur^1].push(tmpst,hm[cur].f[e]); 95 if(map[i+1][j]>0&&map[i][j+1]>0){ 96 tmpst=(st^(left<<ls))^(1<<ls); 97 tmpst=(tmpst^(up<<us))^(2<<us); 98 tmpst<<=2; 99 tmpst|=num; 100 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 101 } 102 if(num<2){ 103 num++; 104 if(map[i][j+1]>0){ 105 tmpst=(st^(left<<ls)); 106 tmpst=(tmpst^(up<<us))^(3<<us); 107 tmpst<<=2; 108 tmpst|=num; 109 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 110 } 111 if(map[i+1][j]>0){ 112 tmpst=(st^(left<<ls))^(3<<ls); 113 tmpst=(tmpst^(up<<us)); 114 if(j==m) tmpst>>=2; 115 tmpst<<=2; 116 tmpst|=num; 117 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 118 } 119 } 120 } 121 else if(left&&up){ 122 if(left==1&&up==1){ 123 int tt=fd_r(j); 124 tts=(m-tt)*2; 125 tmpst=(st^(code[tt]<<tts))^(1<<tts); 126 tmpst=(tmpst^(left<<ls)); 127 tmpst=(tmpst^(up<<us)); 128 tmpst<<=2; 129 tmpst|=num; 130 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 131 } 132 else if(left==2&&up==2){ 133 int tt=fd_l(j-1); 134 tts=(m-tt)*2; 135 tmpst=(st^(code[tt]<<tts))^(2<<tts); 136 tmpst=(tmpst^(left<<ls)); 137 tmpst=(tmpst^(up<<us)); 138 if(j==m) tmpst>>=2; 139 tmpst<<=2; 140 tmpst|=num; 141 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 142 } 143 else if(left==2&&up==1){ 144 tmpst=(st^(left<<ls)); 145 tmpst=(tmpst^(up<<us)); 146 if(j==m) tmpst>>=2; 147 tmpst<<=2; 148 tmpst|=num; 149 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 150 } 151 else if(left==3&&up==3){ 152 tmpst=(st^(left<<ls)); 153 tmpst=(tmpst^(up<<us)); 154 if(j==m) tmpst>>=2; 155 tmpst<<=2; 156 tmpst|=num; 157 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 158 } 159 else if(left==3&&up!=3){ 160 int tt; 161 if(up==1) tt=fd_r(j); 162 else tt=fd_l(j); 163 tts=(m-tt)*2; 164 tmpst=st^(left<<ls); 165 tmpst=tmpst^(up<<us); 166 tmpst=(tmpst^(code[tt]<<tts))^(3<<tts); 167 if(j==m) tmpst>>=2; 168 tmpst<<=2; 169 tmpst|=num; 170 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 171 } 172 else if(left!=3&&up==3){ 173 int tt; 174 if(left==1) tt=fd_r(j-1); 175 else tt=fd_l(j-1); 176 tts=(m-tt)*2; 177 tmpst=st^(left<<ls); 178 tmpst=tmpst^(up<<us); 179 tmpst=(tmpst^(code[tt]<<tts))^(3<<tts); 180 if(j==m) tmpst>>=2; 181 tmpst<<=2; 182 tmpst|=num; 183 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 184 } 185 } 186 else{ 187 int tt,cott; 188 if(left) tt=left; 189 else tt=up; 190 if(map[i][j+1]>0){ 191 tmpst=st^(up<<us)^(tt<<us); 192 tmpst=tmpst^(left<<ls); 193 tmpst<<=2; 194 tmpst|=num; 195 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 196 } 197 if(map[i+1][j]>0){ 198 tmpst=st^(left<<ls)^(tt<<ls); 199 tmpst=tmpst^(up<<us); 200 if(j==m) tmpst>>=2; 201 tmpst<<=2; 202 tmpst|=num; 203 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 204 } 205 if(tt==3&&num<2){ //忘了限制条件<2,WA了N久。 206 tmpst=st^(left<<ls)^(up<<us); 207 if(j==m) tmpst>>=2; 208 tmpst<<=2; 209 tmpst|=(num+1); 210 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 211 } 212 if(left!=3&&up!=3&&num<2){ 213 int sp=(tt==left? j-1: j); 214 tts=(m-sp)*2; 215 if(tt==1) cott=fd_r(sp); 216 else cott=fd_l(sp); 217 tmpst=st^(code[sp]<<tts)^(code[cott]<<((m-cott)*2))^(3<<((m-cott)*2)); 218 if(j==m) tmpst>>=2; 219 num++; 220 tmpst<<=2; 221 tmpst|=num; 222 hm[cur^1].push(tmpst,hm[cur].f[e]+map[i][j]); 223 } 224 } 225 } 226 } 227 228 void dpblock(int i,int j,int cur){ 229 int em; int tmpst; 230 for(int k=0;k<hm[cur].size;k++){ 231 int st=hm[cur].state[k]; 232 num=st&3; 233 st>>=2; 234 decode(st); 235 tmpst=st^(code[j]<<((m-j)*2))^(code[j-1]<<((m-j+1)*2)); 236 if(j==m) tmpst>>=2; 237 tmpst<<=2; 238 tmpst|=num; 239 hm[cur^1].push(tmpst,hm[cur].f[k]); 240 } 241 } 242 243 void solve(){ 244 int cur=0,i; 245 hm[cur].init(); 246 hm[cur].push(0,0); 247 for( i=1;i<=n;i++){ 248 for(int j=1;j<=m;j++){ 249 hm[cur^1].init(); 250 if(map[i][j]>0) dpblank(i,j,cur); 251 else dpblock(i,j,cur); 252 cur=cur^1; 253 } 254 } 255 for( i=0;i<hm[cur].size;i++) 256 if(hm[cur].f[i]>ans) ans=hm[cur].f[i]; 257 printf("%d\n",ans); 258 } 259 260 int main(){ 261 int T; int i,j; 262 scanf("%d",&T); 263 while(T--){ 264 ans=0; 265 scanf("%d%d",&n,&m); 266 memset(map,0,sizeof(map)); 267 for(i=1;i<=n;i++){ 268 for(j=1;j<=m;j++){ 269 scanf("%d",&map[i][j]); 270 if(map[i][j]>ans) ans=map[i][j]; 271 } 272 } 273 solve(); 274 } 275 return 0; 276 }