Solitaire
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4522 Accepted Submission(s): 1369
Problem Description
Solitaire is a game played on a chessboard 8x8. The rows and columns of the chessboard are numbered from 1 to 8, from the top to the bottom and from left to right respectively.
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.
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.
Input
Each of two input lines contains 8 integers a1, a2, ..., a8 separated by single spaces and describes one configuration of pieces on the chessboard. Integers a2j-1 and a2j (1 <= j <= 4) describe the position of one piece - the row number and the column number respectively. Process to the end of file.
Output
The output should contain one word for each test case - YES if a configuration described in the second input line is reachable from the configuration described in the first input line in at most 8 moves, or one word NO otherwise.
Sample Input
4 4 4 5 5 4 6 5 2 4 3 3 3 6 4 6
Sample Output
YES思路:用一个 vis[8][8][8][8][8][8][8][8]数组来记录之前到达过的状态,之后就是一般的广搜。。。呕心沥血一整天,总是因为一些小的问题找了半天错误,以后还是得细心。。。1.用一个bool ed[9][9]数组来保存最后应该到达的状态2.用当前状态值通过check(node)函数与目标状态进行比对,比对成功bfs()结束代码:#include<stdio.h> #include<string.h> #include<queue> using namespace std; struct Node { int step; int map[4][2]; friend bool operator<(Node a,Node b) { return a.step>b.step; } }; bool vis[8][8][8][8][8][8][8][8]; int v[4][2]={-1,0,1,0,0,-1,0,1}; bool ed[9][9]; int st[4][2]; bool mark[9][9]; int maxx; bool check(Node node)//检查是否达到目标状态 { int count=0; for(int i=0;i<4;i++) { int x=node.map[i][0]; int y=node.map[i][1]; // printf("%d %d ",x,y); if(ed[x][y]) count++; } // printf(" count=%d\n",count); return count==4; } bool isVis(Node node)//判断是否出现过该状态 { Node temp=node; int x1=temp.map[0][0]; int y1=temp.map[0][1]; int x2=temp.map[1][0]; int y2=temp.map[1][1]; int x3=temp.map[2][0]; int y3=temp.map[2][1]; int x4=temp.map[3][0]; int y4=temp.map[3][1]; // printf("x1 y1 x2 y2 x3 y3 x4 y4\n"); // printf("%d %d %d %d %d %d %d %d\n",x1,y1,x2,y2,x3,y3,x4,y4); if(vis[x1][y1][x2][y2][x3][y3][x4][y4]) return true; //若未出现,则对当前四个坐标所有的排列进行标记 vis[x1][y1][x2][y2][x3][y3][x4][y4]=true; vis[x1][y1][x2][y2][x4][y4][x3][y3]=true; vis[x1][y1][x3][y3][x4][y4][x2][y2]=true; vis[x1][y1][x3][y3][x2][y2][x4][y4]=true; vis[x1][y1][x4][y4][x2][y2][x3][y3]=true; vis[x1][y1][x4][y4][x3][y3][x2][y2]=true; vis[x2][y2][x1][y1][x3][y3][x4][y4]=true; vis[x2][y2][x1][y1][x4][y4][x3][y3]=true; vis[x2][y2][x3][y3][x1][y1][x4][y4]=true; vis[x2][y2][x3][y3][x4][y4][x1][y1]=true; vis[x2][y2][x4][y4][x1][y1][x3][y3]=true; vis[x2][y2][x4][y4][x3][y3][x1][y1]=true; vis[x3][y3][x1][y1][x2][y2][x4][y4]=true; vis[x3][y3][x1][y1][x4][y4][x2][y2]=true; vis[x3][y3][x2][y2][x1][y1][x4][y4]=true; vis[x3][y3][x2][y2][x4][y4][x1][y1]=true; vis[x3][y3][x4][y4][x1][y1][x2][y2]=true; vis[x3][y3][x4][y4][x2][y2][x1][y1]=true; vis[x4][y4][x1][y1][x2][y2][x3][y3]=true; vis[x4][y4][x1][y1][x3][y3][x2][y2]=true; vis[x4][y4][x2][y2][x1][y1][x3][y3]=true; vis[x4][y4][x2][y2][x3][y3][x1][y1]=true; vis[x4][y4][x3][y3][x1][y1][x2][y2]=true; vis[x4][y4][x3][y3][x2][y2][x1][y1]=true; return false; } int bfs() { priority_queue<Node>q; Node node; node.step=0; for(int i=0;i<4;i++)//初始状态入队列 { node.map[i][0]=st[i][0]; node.map[i][1]=st[i][1]; // printf("st==%d %d\n",node.map[i][0],node.map[i][1]); } q.push(node); isVis(node); int flag=false; while(!q.empty()) { if(maxx<q.size()) maxx=q.size(); node=q.top(); q.pop(); if(check(node)) { // printf("q.maxsize===%d\n",maxx); // printf("step==%d\n",step); // printf("%d %d %d %d %d %d %d %d\n",node.map[0][0],node.map[0][1],node.map[1][0],node.map[1][1],node.map[2][0],node.map[2][1],node.map[3][0],node.map[3][1]); return node.step; } memset(mark,false,sizeof(mark)); for(int k=0;k<4;k++) //以当前坐标值构建一个mark图 ,用于判断移动过后是否与其他三个位置重合 { mark[node.map[k][0]][node.map[k][1]]=true; } for(int i=0;i<4;i++)//四个方向 { for(int j=0;j<4;j++) { Node temp=node; int xx=node.map[j][0]+v[i][0]; int yy=node.map[j][1]+v[i][1]; int step=node.step+1; if(xx<0||xx>=8||yy<0||yy>=8) continue;//边界条件 if(step>8) continue; if(mark[xx][yy]&&!mark[xx+v[i][0]][yy+v[i][1]])//当前方向下一位置有一个棋子,且棋子后为空格 { xx+=v[i][0]; yy+=v[i][1]; if(xx<0||xx>=8||yy<0||yy>=8) continue; } if(mark[xx][yy]) continue;//检测重合,判断棋子是否有重叠的情况 temp.map[j][0]=xx; temp.map[j][1]=yy; temp.step=step; if(check(temp)) return temp.step;//进入队列前与目标状态进行比对,若达到目标状态可以直接省去队列中现有的状态 if(isVis(temp)) continue;//判断之前是否出现过该状态 q.push(temp); } } } return -1; } int main() { memset(st,0,sizeof(st)); int a,b; // freopen("out.doc","w",stdout); while(~scanf("%d%d",&st[0][0],&st[0][1])) { //应为vis长度为8,输入值-1 st[0][0]-=1; st[0][1]-=1; for(int i=1;i<4;i++) { scanf("%d%d",&a,&b); a--; b--; st[i][0]=a; st[i][1]=b; } memset(ed,false,sizeof(ed)); for(int i=0;i<4;i++) { scanf("%d%d",&a,&b); a--; b--; ed[a][b]=true; } memset(vis,false,sizeof(vis)); int ans=-1; maxx=0; ans=bfs(); if(ans>=0) printf("YES\n"); else printf("NO\n"); // printf("ans==%d max==%d\n",ans,maxx); } } /* 4 4 4 5 5 4 6 5 2 4 3 3 3 6 4 6 1 2 2 3 3 4 4 5 1 3 2 4 3 5 4 6 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 4 4 4 5 5 4 6 5 4 4 4 5 5 4 6 5 1 1 1 2 1 3 1 4 3 1 3 2 3 3 3 4 */