传送门:http://acm.fzu.edu.cn/problem.php?pid=2180
Problem 2180 骑士
Time Limit: 5000 mSec Memory Limit : 32768 KB
Problem Description
在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上。
给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步数完成任务。
Input
第一行有一个正整数T(T<=10) 表示一共有T组数据 接下来有T个5*5的矩形。0表示白色骑士1表示黑色骑士,*表示空位。(每组数据间有空行)
Output
对每组数据都输出一行。如果能在15不以内(包括15)到达目标状态,则输出步数,否则输出“Bored!”没有引号。
Sample Input
2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
Sample Output
7
Bored!
Source
FOJ有奖月赛-2014年11月这是FZU的一道月赛的题,蒟蒻实在无奈,只能做搜索题。
本题大致思路:双向BFS,用map套hash来存出现这个状态的时候走的步数。我把从开始状态搜的记为s。(比如map ss和queue sq),从目标状态搜的记为t。
简单的讲一下我的双向BFS。要求要一层一层的搜,s的一层搜完了,在搜t那边一层的。转移出的状态需要拿到对面去检查是否出现,若出现便纳入统计范围。搜完8层就结束。
题目要求步数小于等于15.
上代码:
#include<cstdio>
#include<cstring>
#include<map>
#include<queue>
#define uLL unsigned long long
using namespace std;
struct node
{
int x,y,s;
char g[7][7];
uLL gethash()
{
uLL res=0;
for(int i=0;i<5;i++)
for(int j=0;j<5;j++) res=res*131+g[i][j];
return res;
}
};
const int d[8][2]={{2,1},{2,-1},{-2,1},{-2,-1},{1,2},{1,-2},{-1,2},{-1,-2}};
const char gg[7][7]={"11111","01111","00*11","00001","00000"};
void init(node &t)
{
t.x=2;
t.y=2;
t.s=0;
for(int i=0;i<5;i++)
for(int j=0;j<5;j++) t.g[i][j]=gg[i][j];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
node s,t;
init(t);
for(int i=0;i<5;i++)
{
char str[10];
scanf("%s",str);
for(int j=0;j<5;j++)
{
s.g[i][j]=str[j];
if(str[j]=='*')
{
s.x=i;
s.y=j;
}
}
}
s.s=0;
if(t.gethash()==s.gethash())
{
printf("0\n");
continue;
}
map<uLL,int>ss,tt;
queue<node>sq,tq;
int now=0;
ss[s.gethash()]=0;
tt[t.gethash()]=0;
sq.push(s);
tq.push(t);
int ans=16;
while(!sq.empty()||!tq.empty())
{
if(now==8) break;
while(!sq.empty()&&sq.front().s==now)
{
node x=sq.front();
sq.pop();
for(int i=0;i<8;i++)
{
int xx,yy;
xx=x.x+d[i][0];
yy=x.y+d[i][1];
if(xx<0||xx>=5||yy<0||yy>=5) continue;
node y=x;
y.g[x.x][x.y]=y.g[xx][yy];
y.x=xx;
y.y=yy;
y.g[xx][yy]='*';
y.s++;
uLL hh=y.gethash();
if(ss.find(hh)!=ss.end()) continue;
if(tt.find(hh)!=tt.end())
{
int tmp=y.s+tt[hh];
if(tmp<ans)
{
ans=tmp;
}
}
ss[hh]=y.s;
sq.push(y);
}
}
while(!tq.empty()&&tq.front().s==now)
{
node x=tq.front();
tq.pop();
for(int i=0;i<8;i++)
{
int xx,yy;
xx=x.x+d[i][0];
yy=x.y+d[i][1];
if(xx<0||xx>=5||yy<0||yy>=5) continue;
node y=x;
y.g[x.x][x.y]=y.g[xx][yy];
y.x=xx;
y.y=yy;
y.g[xx][yy]='*';
y.s++;
uLL hh=y.gethash();
if(tt.find(hh)!=tt.end()) continue;
if(ss.find(hh)!=ss.end())
{
int tmp=y.s+ss[hh];
if(tmp<ans)
{
ans=tmp;
}
}
tt[hh]=y.s;
tq.push(y);
}
}
now++;
}
if(ans==16) printf("Bored!\n");
else printf("%d\n",ans);
}
return 0;
}