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
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
Sample Output
7
Bored!
Bored!
分析:我们从当前进行状态搜索,只需要标记好状态就可以了。首先怎么标记状态:图为5*5,我们考虑用25位二进制表示。黑棋为1,白棋为0,‘*’的的权相当于0, 所以我们用一个int型变量就可以存下这个状态。同时记录'*'的位置,可以用一个值代替它的坐标即index=i*5+j(i,j为'*'的坐标0<=i,j<=4)。所以用map<pair<int,int>,int>映射,表示本状态,'*'位置,出现没。
题意告诉步数<=15,拿最坏的情况15步来说,我们要走15步,每次有8个状态,即8^15,即在队列里要存2^18个node型的数据,显然抄内存。
我们在考虑用双向bfs,正向:从给出的状态搜,反向:从最终的状态搜。
正搜和反搜的一步一步交替的,因此正搜和反搜的步数都不可能超过8。
正搜:在搜的过程中,判断此状态在反向中出现没,若出现则答案为两个状态的步数和。
反搜:
在搜的过程中,判断此状态在正向中出现没,若出现则答案为两个状态的步数和。
代码:
#include<iostream>
#include<string>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<math.h>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int MAXN=7;
char maze[MAXN][MAXN];
int dir[8][2]={-1,2,-1,-2,-2,1,-2,-1,1,2,1,-2,2,1,2,-1};
struct node
{
int x,y;
int sta;
int step;
int indx;
node(int xx=0,int yy=0,int ssta=0,int sstep=0)
{
x=xx;
y=yy;
sta=ssta;
step=sstep;
indx=x*5+y;
}
friend bool operator<(node xx,node yy)
{
return xx.sta<yy.sta;
}
};
map<pair<int,int>,int>mp,mp1;
map<pair<int,int>,int>::iterator it;
struct node st,tx,ty;
int en,ind=12;
bool fun(queue<node>&Q,map<pair<int,int>,int>&MP,map<pair<int,int>,int>&MP1)
{//从此状态向8个方向搜索
pair<int,int>p;
tx=Q.front();
Q.pop();
if(tx.step>=9)
{
return false;
}
p=make_pair(tx.sta,tx.indx);
if(MP1.find(p)!=MP1.end())
{
int ans=MP1[p]+tx.step;
if(ans<=15)
{
printf("%d\n",MP1[p]+tx.step);return true;
}
}
for(int i=0;i<=7;i++)
{
int xx=tx.indx/5+dir[i][0];
int yy=tx.indx%5+dir[i][1];
if(xx>=0&&xx<=4&&yy>=0&&yy<=4)
{
ty=tx;
int temp=xx*5+yy;
int flag=ty.sta&(1<<temp);
if(flag)
{
ty.sta-=1<<(temp);
ty.sta+=1<<(tx.indx);
}
ty.step=tx.step+1;
ty.indx=temp;
ty.x=xx;
ty.y=yy;
p=make_pair(ty.sta,ty.indx);
if(MP.find(p)==MP.end())
{
MP[p]=ty.step;
Q.push(ty);
}
}
}
return false;
}
void bfs()
{
queue<node>q,q1;
mp1.clear();//终状态
pair<int,int>p;
p=make_pair(en,ind);
mp1[p]=1;
q1.push( node(2,2,en,0));
p=make_pair(st.sta,st.indx);//起始状态
mp[p]=1;
st.step=0;
q.push(st);
if(st.sta==en)
{
puts("0");return ;
}
while(!q.empty()&&!q1.empty())
{
bool ans = fun(q,mp,mp1);//正搜
if(ans)return;
ans=fun(q1,mp1,mp);//反搜
if(ans)return;
}
puts("Bored!");
}
int main()
{
int i,j,t,s;
scanf("%d",&t);
char ch[26];
char str[6][6]={"11111","01111","00*11","00001","00000"};
en=0;
for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
if(str[i][j]=='1')
en|=1<<(i*5+j);
}
while(t--)
{
s=0;
mp.clear();
for(i=0;i<5;i++)
{
scanf("%s",ch);
for(j=0;j<5;j++)
{
if(ch[j]=='*')
{
st.x=i;st.y=j;
st.indx=i*5+j;
}
if(ch[j]=='1')s|=(1<<(i*5+j));
}
}
st.sta=s;
bfs();
}
return 0;
}