1. 程式人生 > >poj 1198 / hdu 1401 Solitaire (記憶化搜尋+meet in middle)

poj 1198 / hdu 1401 Solitaire (記憶化搜尋+meet in middle)

題目大意:給你一個8*8的棋盤,上面有四個棋子,給你一個初始排布,一個目標排布,每次移動,可以把一個棋子移動到一個相鄰的空位,或者跨過1個相鄰的棋子,在保證棋子移動不超過8次的情況下,問能否把棋盤上的棋子由初始排布變成目標排布

8*8的棋盤,剛好不爆ull,狀壓那些位置有棋子

然後從初始狀態開始,暴搜出當前狀態下,移動一個棋子之後所有可能到達的狀態

直接搜,總狀態數是8^8,此外還有常數,會爆

由於給定了目標排布,考慮meet in middle

從起始狀態和目標狀態各搜4步即可

為了防止爆棧,同時為了好寫好調,最好用bfs

具體實現呢,可以開兩個佇列正反同時bfs,搜到合法結果就break掉,可以減少很多常數

開2個map,表示正/反著跑能否到達狀態s,如果能到達,則mp[s]=1

以正著搜為例,當前從que1中取出的狀態為s,能到達的下一個狀態為t,如果t出現在map1中,就不必在推入que1了,如果t出現在map2中,說明存在合法狀態,break掉輸出YES

程式碼好長啊..但在搜尋題裡算短的了

  1 #include <map>
  2 #include <queue>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6
#define NN 5010 7 #define MM 2000 8 #define maxn 200 9 #define ll long long 10 #define uint unsigned int 11 #define ull unsigned long long 12 using namespace std; 13 14 int id[10][10]; 15 int xx[4]={-1,0,1,0}; 16 int yy[4]={0,1,0,-1}; 17 ull bin[100]; 18 int ax[5],ay[5],bx[5],by[5];
19 struct node{ 20 ull s;int c; 21 friend bool operator < (const node &s1,const node &s2) 22 {return s1.s<s2.s;} 23 node(ull s,int c):s(s),c(c){} 24 node(){} 25 }; 26 map<ull,int>mp[2]; 27 int check(int x,int y,ull s) 28 { 29 if(x<1||y<1||x>8||y>8)return 0; 30 if(s&bin[id[x][y]]) return 2; 31 return 1; 32 } 33 34 int main() 35 { 36 //freopen("t2.in","r",stdin); 37 for(int i=1;i<=8;i++) 38 for(int j=1;j<=8;j++) 39 id[i][j]=8*(i-1)+j-1; 40 //px[id[i][j]]=i,py[id[i][j]]=j; 41 bin[0]=1; 42 for(int i=1;i<=63;i++) 43 bin[i]=bin[i-1]<<1; 44 while(scanf("%d%d%d%d",&ax[1],&ay[1],&ax[2],&ay[2])!=EOF) 45 { 46 scanf("%d%d%d%d",&ax[3],&ay[3],&ax[4],&ay[4]); 47 scanf("%d%d%d%d",&bx[1],&by[1],&bx[2],&by[2]); 48 scanf("%d%d%d%d",&bx[3],&by[3],&bx[4],&by[4]); 49 queue<node>q[2]; 50 ull s=0,t=0; 51 int cnt=0,fx,fy,fl,nt; 52 for(int i=1;i<=4;i++) 53 s|=bin[id[ax[i]][ay[i]]]; 54 mp[0][s]=1; 55 q[0].push(node(s,0));s=0; 56 for(int i=1;i<=4;i++) 57 s|=bin[id[bx[i]][by[i]]]; 58 mp[1][s]=1; 59 q[1].push(node(s,0)); 60 int ans=0,c,x,y; 61 while((!q[0].empty()||!q[1].empty())&&!ans) 62 { 63 if(!q[0].empty()) 64 { 65 node K=q[0].front();q[0].pop(); 66 s=K.s,c=K.c; 67 for(int i=1;i<=8;i++) 68 for(int j=1;j<=8;j++) 69 { 70 if(!(s&bin[id[i][j]])) continue; 71 for(int k=0;k<4;k++) 72 { 73 x=i+xx[k],y=j+yy[k]; 74 fl=check(x,y,s); 75 if(!fl) continue; 76 if(fl==2){ 77 x+=xx[k],y+=yy[k]; 78 if(check(x,y,s)!=1) continue; 79 } 80 t=(s^bin[id[i][j]])|bin[id[x][y]]; 81 if(mp[0].find(t)!=mp[0].end()) 82 continue; 83 if(mp[1].find(t)!=mp[1].end()) 84 {ans=1;break;} 85 mp[0][t]=1; 86 if(c<3) q[0].push(node(t,c+1)); 87 if(ans==1) break; 88 } 89 } 90 } 91 if(!q[1].empty()) 92 { 93 node K=q[1].front();q[1].pop(); 94 s=K.s,c=K.c; 95 for(int i=1;i<=8;i++) 96 for(int j=1;j<=8;j++) 97 { 98 if(!(s&bin[id[i][j]])) continue; 99 for(int k=0;k<4;k++) 100 { 101 x=i+xx[k],y=j+yy[k]; 102 fl=check(x,y,s); 103 if(!fl) continue; 104 if(fl==2){ 105 x+=xx[k],y+=yy[k]; 106 if(check(x,y,s)!=1) continue; 107 } 108 t=(s^bin[id[i][j]])|bin[id[x][y]]; 109 if(mp[1].find(t)!=mp[1].end()) 110 continue; 111 if(mp[0].find(t)!=mp[0].end()) 112 {ans=1;break;} 113 mp[1][t]=1; 114 if(c<3) q[1].push(node(t,c+1)); 115 if(ans==1) break; 116 } 117 } 118 } 119 } 120 if(ans==1) 121 printf("YES\n"); 122 else 123 printf("NO\n"); 124 mp[0].clear(); 125 mp[1].clear(); 126 } 127 return 0; 128 }