Hdu1401-Solitaire(双向bfs)
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).
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
题意:棋盘大小为8*8,然后有4个球,给出初始所有球的位置以及目标位置,每次可以移动一个球,要么移动到旁边空的地方,要么跨过一个
球到空的地方(不能跨过多个球),问能否在8步以内到达目标状态。
解析:限定了8步,而且前后搜效果是一样的,所以可以考虑用双向bfs,然后8个数哈希,要注意对4个点要排序。
代码
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int mod=500007; const int maxn=200005; int dx[]={-1,0,1,0},dy[]={0,-1,0,1}; bool in(int x,int y){ return x>=1&&x<=8&&y>=1&&y<=8; } struct point //球的坐标 { int x,y; point(int x=0,int y=0):x(x),y(y){} bool operator < (const point& t) const { if(x!=t.x) return x<t.x; return y<t.y; } }; struct node { point p[4]; //每个节点保存4个球的坐标,并且是排好序的 }nod[2][maxn]; //开二维用于双向搜 struct Hash { int v,k,nid,next; //保存哈希值,0或1,下标,next指针 }ha[mod+maxn]; int f[2],r[2],hash_id; //队首队尾指针 bool Same(int k1,int a,int k2,int b) //判断两个结构体是否完全相同 { for(int i=0;i<4;i++) { if(nod[k1][a].p[i].x!=nod[k2][b].p[i].x) return false; if(nod[k1][a].p[i].y!=nod[k2][b].p[i].y) return false; } return true; } int GetHash(point p[]) //得到哈希值 { int ret=0,k=1; for(int i=0;i<4;i++) { ret+=p[i].x*k; k*=3; //k是系数 ret+=p[i].y*k; k*=3; } return ret; } int Insert_Hash(int v,int k,int nid) //插入 { int a=v%mod; int p=ha[a].next; while(p!=-1) { if(ha[p].v==v&&Same(ha[p].k,ha[p].nid,k,nid)) return ha[p].k==k?0:1; //有相同的状态,k值相同返回0,不同返回1 p=ha[p].next; } p=++hash_id; ha[p].v=v; ha[p].k=k; ha[p].nid=nid; //增加新的节点 ha[p].next=ha[a].next; ha[a].next=p; return -1; } bool Has(node& t,int x,int y) { for(int i=0;i<4;i++) if(t.p[i].x==x&&t.p[i].y==y) return true; //此处是球 return false; } bool AddNode(node& t,int i,int j,int k) { int x=t.p[i].x; int y=t.p[i].y; int nx=x+dx[j]; int ny=y+dy[j]; if(!in(nx,ny)) return false; //出界 if(Has(t,nx,ny)) nx+=dx[j],ny+=dy[j]; //有球 if(!in(nx,ny)) return false; //出界 if(Has(t,nx,ny)) return false; //还有球 node& tt=nod[k][r[k]]; tt=t; tt.p[i].x=nx; tt.p[i].y=ny; sort(tt.p,tt.p+4); //排序 int a=Insert_Hash(GetHash(tt.p),k,r[k]); if(a==1) return true; //找到解 else if(a==-1) r[k]++; //增加新节点 return false; } bool bfs(int k) { int en=r[k]; while(f[k]<en) { node& t=nod[k][f[k]++]; for(int i=0;i<4;i++) //4个球4个方向 for(int j=0;j<4;j++) if(AddNode(t,i,j,k)) return true; } return false; } bool solve() { if(Same(0,0,1,0)) return true; //相同 int step=0; f[0]=f[1]=0; r[0]=r[1]=1; for(int i=0;i<mod;i++) ha[i].next=-1; hash_id=mod-1; Insert_Hash(GetHash(nod[0][0].p),0,0); Insert_Hash(GetHash(nod[1][0].p),1,0); while(f[0]<r[0]||f[1]<r[1]) { if(step>=4) return false; step++; if(bfs(0)) return true; if(bfs(1)) return true; } return false; } int main() { int x,y; while(scanf("%d%d",&x,&y)!=EOF) { nod[0][0].p[0]=point(x,y); for(int i=1;i<4;i++) { scanf("%d%d",&x,&y); nod[0][0].p[i]=point(x,y); } for(int i=0;i<4;i++) { scanf("%d%d",&x,&y); nod[1][0].p[i]=point(x,y); } sort(nod[0][0].p,nod[0][0].p+4); sort(nod[1][0].p,nod[1][0].p+4); if(solve()) printf("YES\n"); else printf("NO\n"); } return 0; }