#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> //#define DBG //#define INPUT //#define DBG1 using namespace std; /** Problem: poj1198 - Solitaire Begin Time : 18:33 15th/Mar/2012 End Time: 2:40 a.m. 16th/Mar/2012 Test Data: 见数据生成器代码 Standard Output: 用本程序对拼即可 Thought: 这个代码写的太垃圾了,比较崩溃。 ①:状态压缩: 棋盘上只有四个棋子,一行数字(x1 y1 x2 y2 x3 y3 x4 y4) 代表了四个棋子在棋盘上的位置。 我们把各个棋子按照x的大小进行排序。 然后把其变成一个八位数来表示当前的棋盘状态 ②:HASH排重 (*) 把待搜索的棋盘状态插入自己的hash表中。 注意,由于DFS是双向的,hash表要维护两个,一个是正向搜索的hash表 一个是反向搜索的hash表。如果其的key发生冲突并且内容相同,那么插入失败。 ③:状态搜索: 每次从两个队列(一个表示从开始状态,一个表示从结束状态)搜索中取出表示该次搜索 应该搜索的状态,然后将搜索的内容在不同的hash表里进行检索,例如: 从begin_queue[front]取出的bval1(表示从开始状态搜索到的某个中间状态) 应该在end_hash中检索,如果在end_hash中找到了该状态,并且该状态对应的 end_deep(从结束状态到这个中间状态经过的步数)与当前状态的deep加起来小于等于8 那么就代表找到了,标志isFound = true;然后输出 ④:如何搜索 搜索的时候还是四个向量,左右上下,只不过进行左右上下搜索的时候记得判断一下周围是否有棋子 这个做法是把压缩过的状态还原成int tmp[8],然后找移动后的棋子tmp[i],tmp[i+1]在其他的tmp中有 没有相同的,2*i是x,2*i+1是y 如果tmp[2*i] == tmp[2*j] && tmp[2*i + 1] == tmp[2*j + 1]的话,就代表i移动后与j重叠。 按照“跳过子”的规则进行移动。 Knowledge: HASH排重+状态压缩+双向BFS搜索 The Experience: WA点1 : 在进行棋子的移动的时候,switch(dir) case 0 1 2 3写成了 1 2 3 4,不应该犯! WA点2:非常脑残的在hash表中每个状态没有保存对应的深度!所以有时候从beginState搜索到beginDeep = 3 的时候,在endHash表中找到了一个endDeep = 6 的状态与之对应,由于没有保存endHash中每个状态的深度 所以这时候输出了,WA了4次(貌似) */ const int HASHKEY = 100003; const int HASHEND = 2; const int HASHBEGIN = 1; const int dx[] = {-1,1,0,0}; const int dy[] = {0,0,-1,1}; int bs[8]; ///开始状态 int es[8]; ///结束状态 int bhash[200000]; int bnext[200000]; int ehash[200000]; int enext[200000]; int _bdeep1[500000]; int _edeep1[500000]; int _bdeep[500000]; int _edeep[500000]; int bque[500000]; int eque[500000]; bool isFound; int bnow,enow; int bfront,brear; int bdeep,edeep; int efront,erear; bool checkHash(int val,int sel,int dp) { int tmp = val % HASHKEY; if( sel == HASHBEGIN ) { while(bnext[tmp]) { if ( bhash[ bnext[tmp] ] == val ) { #ifdef DBG printf("The %d of bhash is %d\n",bnext[tmp],val); #endif if ( _bdeep1[ bnext[tmp] ] + dp <= 8) return true; else return false; } tmp = bnext[tmp]; } } if( sel == HASHEND ) { while(enext[tmp]) { if (ehash[ enext[tmp] ] == val) { #ifdef DBG printf("The %d of ehash is %d\n",bnext[tmp],val); #endif if (_edeep1 [ enext[tmp] ] + dp <= 8 ) return true; else return false; } tmp = enext[tmp]; } } return false; } bool insert_end(int es,int dp) { int key = es % HASHKEY; while( enext[key] ) { if( ehash[ enext[key] ] == es) return false; key = enext[key]; } enext[key] = enow; _edeep1[enow] = dp; ehash[enow] = es; enow++; return true; } bool insert_begin(int bs,int dp) { ///检查是否在hashend里 int key = bs % HASHKEY; while( bnext[key] ) { if ( bhash[ bnext[key] ] == bs ) return false; key = bnext[key]; } bnext[key] = bnow; bhash[bnow] = bs; _bdeep1[bnow] = dp; bnow++; return true; } void exchange(int* a, int* b) { int tmp; tmp = *a; *a = *b; *b = tmp; } int getNum(int a[8]) { for(int i = 0 ; i < 8 ; i = i + 2) { for (int j = i + 2 ; j < 8 ; j = j + 2) { if ( a[i] > a[j] ) { exchange(&a[i],&a[j]); exchange(&a[i+1],&a[j+1]); } if ( a[i] == a[j] ) { if ( a[i+1] > a[j+1] ) { exchange(&a[i+1],&a[j+1]); } } } } ///排序 int res = 0 ; for(int i = 0 ; i < 8 ; i++) { res = res * 10 + a[i]; } return res; } /** int getNum(const int a[8]) { ///这里写的有问题 ///应该把node按照x,y的顺序排序之后再给值! int res = 0; for(int i = 0 ; i < 8; i++) { res = res * 10 + a[i]; } return res; }*/ bool checkMove(int* destState,int oriState[8],int ind,int dir) { for(int i = 0 ; i < 8; i = i + 2) { if( destState[ind] == oriState[i] ) { if (destState[ind+1] == oriState[i+1] ) { ///棋子发生重叠 ///dir - >方向 switch(dir) { case 0: ///上,x-1,x - 1 -1 ->越过棋子 if( destState[ind] - 1 > 0 ) ///不出界 { destState[ind] = destState[ind] - 1; return true; } break; case 1: ///下, x+1 if ( destState[ind] + 1 < 9 ) { destState[ind] += 1; return true; } break; case 2: ///左,y-1 if ( destState[ind+1] - 1 > 0 ) { destState[ind+1] -=1; return true; } break; case 3: ///右,y+1 if ( destState[ind+1] + 1 < 9 ) { destState[ind+1] +=1; return true; } break; } return false; } } } /////////////////////上方为检测棋子重叠 if ( destState[ind] < 1 || destState[ind] > 8 || destState[ind+1] > 8 || destState[ind+1] < 1 ) return false; return true; } void segNum(int* a,int val) { for(int i = 7 ; i >= 0 ; i--) { a[i] = val % 10; val = val / 10; } } void Solve() { int btmp[8]; int etmp[8]; int btmp1[8],etmp1[8]; int bval = 0; int bval1 = 0; int eval = 0; int bdeep1,edeep1; int eval1 = 0; int bnum,_enum; //enum is the keyword isFound = false; bfront = 1; brear = 2; bdeep = edeep = 0; efront = 1; erear = 2; bnow = enow = 1; memcpy(btmp,bs,sizeof(int)*8); memcpy(etmp,es,sizeof(int)*8); memset(bque,0,sizeof(bque)); memset(eque,0,sizeof(eque)); memset(bnext,0,sizeof(bnext)); memset(enext,0,sizeof(enext)); memset(bhash,0,sizeof(bhash)); memset(ehash,0,sizeof(ehash)); bnum = getNum(btmp); _enum = getNum(etmp); insert_begin(bnum,bdeep); insert_end(_enum,edeep); bque[bfront] = bnum; eque[efront] = _enum; _bdeep[bfront] = bdeep; _edeep[efront] = edeep; while( bfront < brear && efront < erear && !isFound ) { ///双向搜索 bval = bque[bfront]; eval = eque[efront]; bdeep = _bdeep[bfront]; edeep = _edeep[efront]; // if ( bdeep + edeep >= 6 ) if(checkHash(bval,HASHEND,bdeep)) { isFound = true; } if(checkHash(eval,HASHBEGIN,edeep)) { isFound = true; } #ifdef DBG if( isFound ) { printf("Founded at deep of : \n"); printf("Begin Deep : %d \n",bdeep); printf("End Deep : %d \n",edeep); printf("The end is %d\n",eval1); printf("The Start is %d\n",bval1); } #endif if(isFound) return; if( bdeep + edeep > 8 ) break; segNum(btmp,bval); segNum(etmp,eval); ///这里就比较郁闷了,对于每个棋子都要展开, ///对于每个棋子的移动都要判断是否符合规矩 ///其实rear代表着队列里面的节点数,我们从节点少的开始展开。 for(int i = 0 ; i < 4 ; i++) ///四个棋子 { // memcpy(btmp1,btmp,sizeof(btmp)); // memcpy(etmp1,etmp,sizeof(etmp)); for(int j = 0 ; j < 4 ; j++) ///四个方向 { memcpy(btmp1,btmp,sizeof(btmp)); memcpy(etmp1,etmp,sizeof(etmp)); if(isFound) break; btmp1[2*i] = btmp[2*i] + dx[j]; btmp1[2*i+1] = btmp[2*i+1] + dy[j]; ///开始节点,x,y的移动 etmp1[2*i] = etmp[2*i] + dx[j]; etmp1[2*i+1] = etmp[2*i+1] + dy[j]; ///最终节点,x,y的移动 if ( checkMove(btmp1,btmp,2*i,j) ) { bval1 = getNum(btmp1); if(insert_begin(bval1,bdeep+1)) { bque[brear] = bval1; _bdeep[brear] = bdeep + 1; brear++; } } if ( checkMove(etmp1,etmp,2*i,j)) { eval1 = getNum(etmp1); if(insert_end(eval1,edeep+1)) { eque[erear] = eval1; _edeep[erear] = edeep + 1; erear++; } } } } bfront++; efront++;///bdeep++;edeep++; } } int main() { #ifdef INPUT freopen("b:\\acm\\poj1198\\input.txt","r",stdin); freopen("b:\\acm\\poj1198\\output1.txt","w",stdout); #endif #ifdef DBG1 int a = 1; #endif while(scanf("%d",&bs[0]) != EOF) { #ifdef DBG1 printf("Process condition : %d\n",a); a++; #endif for(int i = 1 ; i < 8 ; i++) { scanf("%d",&bs[i]); } for(int i = 0 ; i < 8 ; i++) { scanf("%d",&es[i]); } Solve(); if (isFound) { printf("YES\n"); } else { printf("NO\n"); } } #ifdef INPUT fclose(stdin); fclose(stdout); #endif return 0; }