题目链接: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;
}