Solitaire
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3337 Accepted Submission(s): 1046
There are four identical pieces on the board. In one move it is allowed to:
> move a piece to an empty neighboring field (up, down, left or right),
> jump over one neighboring piece to an empty field (up, down, left or right).
There are 4 moves allowed for each piece in the configuration shown above. As an example let's consider a piece placed in the row 4, column 4. It can be moved one row up, two rows down, one column left or two columns right.
Write a program that:
> reads two chessboard configurations from the standard input,
> verifies whether the second one is reachable from the first one in at most 8 moves,
> writes the result to the standard output.
number and the column number respectively. Process to the end of file.
4 4 4 5 5 4 6 5 2 4 3 3 3 6 4 6
YES
/* 1401 双向BFS 普通广度优先搜索的复杂度:有4颗棋子,每个棋子最多有4种变换方式, 所以一个棋盘可以对应16种状态,走8步的话,就有16^8 = 2^32的计算量。 给定两种状态,判断是否可达。操作的特别之处:操作具有可逆性, 也就是说,从A到B状态,B到A依然是可行的。 可虑一下双向广搜,先判断复杂度:两个状态各进行4步操作,计算量为16^4=2^16, 时空复杂度都可以满足。 考虑到这里不要求最小步数,我们可以先把两种状态各走四步的可达状态先用广搜算出存表, 然后直接查表比较即可。 有一个剪枝的问题需要考虑,现在给4个piece编号,1,2,3,4. 如果在某种情况下存在{4,4}{4,5}{4,6}{4,7},之后又出现{4,4}{4,6}{4,5}{4,7}, 虽然在hash表里不同,但实际上是重复的mode,因此需要给4个piece进行排序。 */ #include<iostream> #include<stdio.h> #include<algorithm> #include<queue> #include<map> using namespace std; const int dir[4][2] = {1,0,-1,0,0,1,0,-1}; const int pow[8] = {1,8,64,512,4096,32768,262144,2097152}; struct point{ int x,y; }; struct node{ point chess[4]; bool check(int k) { if(chess[k].x>=0&&chess[k].x<=7&&chess[k].y>=0&&chess[k].y<=7) { for(int i=0;i<4;i++) { if(i!=k&&chess[i].x==chess[k].x&&chess[i].y==chess[k].y) return false; } return true; } return false; } }; node s,e; map<int,int> mm; map<int,int>::iterator it1,it2; bool cmp(struct point a,struct point b) { if(a.x==b.x) return a.y<b.y; return a.x<b.x; } int gethash(node& a) { sort(a.chess,a.chess+4,cmp); int hash=0; for(int i=0;i<4;i++) { hash+=a.chess[i].x*pow[2*i]; hash+=a.chess[i].y*pow[2*i+1]; } return hash; } bool BFS(node temp,int flag) { queue<node> que; int i,j; que.push(temp); while(!que.empty()) { temp=que.front(); que.pop(); it1=mm.find(gethash(temp)); if((it1->second)%10>=4) //移动步数超过4步 continue; for(i=0;i<4;i++)//四个棋子 { for(j=0;j<4;j++)//四个方向 { node next=temp; next.chess[i].x+=dir[j][0]; next.chess[i].y+=dir[j][1]; if(!next.check(i))//重叠或者越界 { next.chess[i].x+=dir[j][0];//多走一步 next.chess[i].y+=dir[j][1]; if(!next.check(i))//重叠或者越界 continue; } int hash2=gethash(next);// next的hash it2=mm.find(hash2); if(it2==mm.end())//不存在 { mm[hash2]=it1->second+1;//步数+1 que.push(next); } else if(it2->second/10==1-flag)//存在 s/10=0走到1结束 e=1走到0结束 { return true; } } } } return false; } int main() { int i; while(scanf("%d",&s.chess[0].x)!=EOF) { scanf("%d",&s.chess[0].y); for(i=1;i<4;i++) scanf("%d%d",&s.chess[i].x,&s.chess[i].y); for(i=0;i<4;i++) scanf("%d%d",&e.chess[i].x,&e.chess[i].y); for(i=0;i<4;i++) { s.chess[i].x--;s.chess[i].y--; e.chess[i].x--;e.chess[i].y--; } mm[gethash(s)]=10*0+0;//hash存储 map映射表示对应的s ,步数 mm[gethash(e)]=10*1+0;//s是0 e是1 if(BFS(s,0)||BFS(e,1)) printf("YES\n"); else printf("NO\n"); mm.clear(); } }