题目链接:Click here~~
题意:
1个8x8的棋盘有4个棋子,棋子可以上下左右走(包括跳过相邻的一个)。
给出初始状态与目标状态,问8步之内,能否到达。
解题思路:
一直听说有“双向BFS”这个词,今天终于学了。
如果单纯从1个状态开始搜索的话,每步有16种状态需要扩展,复杂度为O(16^8),不可解。
如果从2个状态同时搜,那么,每个状态只需要搜4步,复杂度为O(2*16^4),就可解了。
其他都好说,保存状态的hash值时,需要注意排序,另外开数组存hash值的话内存太大,可以用set来存hash值。
贴上代码,供大家交流吧。
其实同样的思想,这题也应该可以用dfs做,但应该比bfs慢,等有空了再写。
#include <set> #include <queue> #include <stdio.h> #include <algorithm> using namespace std; struct Point { int x,y; Point(){} Point(int x,int y):x(x),y(y){} bool operator < (const Point& p)const { return x<p.x || x==p.x && y<p.y; } bool operator == (const Point& p)const { return x==p.x && y==p.y; } bool Read() { return scanf("%d%d",&x,&y) != EOF; } }; struct Graph { Point p[4]; bool Read() { if(!p[0].Read()) return false; for(int i=1;i<4;i++) p[i].Read(); return true; } int HASH() { sort(p,p+4); int res = 0; for(int i=0;i<4;i++) { int tmp = (p[i].x-1)*8 + p[i].y-1; res = res*64 + tmp; } return res; } bool operator == (Graph& g) { return HASH() == g.HASH(); } }; struct Node { Graph g; int step; Node(){} Node(const Graph& g,int s):g(g),step(s){} }G[2]; const int dx[]={1,0,-1,0}; const int dy[]={0,1,0,-1}; queue<Node> q[2]; set<int> Hash[2]; bool legal(const Point& p) { return 1<=p.x && p.x<=8 && 1<=p.y && p.y<=8; } bool repeat(const Graph& g,const Point& p) { for(int i=0;i<4;i++) if(g.p[i] == p) return true; return false; } bool bfs(int k,int layer) { while(!q[k].empty() && q[k].front().step==layer) { Node T = q[k].front(); q[k].pop(); for(int i=0;i<4;i++) { for(int j=0;j<4;j++) { Point next(T.g.p[i].x+dx[j], T.g.p[i].y+dy[j]); if(!legal(next)) continue; if(repeat(T.g,next)) { next.x += dx[j]; next.y += dy[j]; if(!legal(next) || repeat(T.g,next)) continue; } Node TT = T; TT.g.p[i] = next; int hash = TT.g.HASH(); if(Hash[k^1].count(hash)) return true; if(Hash[k].count(hash)) continue; Hash[k].insert(hash); if(layer <= 2) q[k].push(Node(TT.g,layer+1)); } } } return false; } bool two_bfs() { if(G[0].g == G[1].g) return true; for(int layer=0;layer<=3;layer++) { if(bfs(0,layer) || bfs(1,layer)) return true; } return false; } void clear(queue<Node>& Q) { while(!Q.empty()) Q.pop(); } int main() { while(G[0].g.Read() && G[1].g.Read()) { for(int i=0;i<=1;i++) { clear(q[i]); Hash[i].clear(); Hash[i].insert(G[i].g.HASH()); G[i].step = 0; q[i].push(G[i]); } puts(two_bfs()?"YES":"NO"); } return 0; }