题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1401
http://poj.org/problem?id=1198
题意:给出两个棋局状态,问能不能在八步之内按照所给出的行棋规则从初始状态走到终止状态.
题目分析:搜索题,但是,每一个状态的后继状态有4*4种状态之多,还要考虑到棋盘的存储,用一般的广搜的话跑起来肯定有些吃力,又根据题意,明显行棋规则具有逆向性,所以采用双向广搜的方法进行解题.其中的棋盘映射用到了STLmap,看来得学学hash了~
#pragma warning (disable:4786) #include<stdio.h> #include<queue> #include<map> using namespace std; typedef struct p{ int x,y; }Point; //共有四颗棋子,棋盘大小为64,采用位棋盘表示 typedef struct Map{ unsigned __int64 value; Point p[4]; int steps,which; void getvalue() {//棋盘对应键值 value=0; for(short i=0;i<4;i++) value+=(unsigned __int64)1<<((p[i].x-1)*8+(p[i].y-1)); } }Map; struct Cmp{ bool operator () (const Map &a,const Map &b) const { return a.value<b.value; } }; map<Map,int,Cmp>m; queue<Map>q; Map start,end; int dir[][2]={{0,1},{0,-1},{1,0},{-1,0}}; bool Next(Map cur,Map &next,int ith,int d) {//获取第ith个棋子d方向上的下一个棋面状态 int i,j; next.p[ith].x=cur.p[ith].x+dir[d][0]; next.p[ith].y=cur.p[ith].y+dir[d][1]; if(next.p[ith].x<1||next.p[ith].x>8||next.p[ith].y<1||next.p[ith].y>8) return false; for(i=1;i<4;i++){ if(next.p[ith].x==cur.p[(ith+i)%4].x&&next.p[ith].y==cur.p[(ith+i)%4].y){ next.p[ith].x+=dir[d][0]; next.p[ith].y+=dir[d][1]; if(next.p[ith].x<1||next.p[ith].x>8||next.p[ith].y<1||next.p[ith].y>8) return false; for(j=1;j<4;j++){ if(next.p[ith].x==cur.p[(ith+j)%4].x &&next.p[ith].y==cur.p[(ith+j)%4].y) return false; } return true; } } return true; } bool bfs() {//双向搜索 Map cur,next; int i,d,k,v; m.clear(); while(!q.empty()) q.pop(); start.steps=end.steps=0; start.which=1;end.which=2; start.getvalue();end.getvalue(); m[start]=1;m[end]=2; q.push(start);q.push(end); while(!q.empty()){ cur=q.front(); q.pop(); v=m[cur]; if(cur.steps>4) break; if(v!=0&&v!=cur.which) return true; for(i=0;i<4;i++){//每一颗棋子 for(d=0;d<4;d++){//每一个方向 if(Next(cur,next,i,d)){ for(k=1;k<4;k++) next.p[(i+k)%4]=cur.p[(i+k)%4]; next.steps=cur.steps+1; next.which=cur.which; next.getvalue(); if(next.steps>4) continue; v=m[next]; if(v==next.which) continue; if(v&&v!=next.which) return true; m[next]=next.which; q.push(next); } } } } return false; } int main() { int i; while(1){ for(i=0;i<4;i++){ if(scanf("%d%d",&start.p[i].x,&start.p[i].y)==EOF) return 0; } for(i=0;i<4;i++) scanf("%d%d",&end.p[i].x,&end.p[i].y); printf(bfs()?"YES/n":"NO/n"); } return 0; }