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 }