题目大意:
一个的棋盘上有个点不可以走,求马(骑士)从走到的最少步数。
10
c1 d1 d5 c2 c3 c4 d2 d3 d4 c5
a1 f1
0
c1 b3
2
b3 c2
a1 b2
-1
Board 1: 7 moves
Board 2: 1 moves
Board 3: not reachable
思路:
BFS
比较裸的广搜吧。。。
将个点赋值为1,表示不可以走,到时候走过的点也赋值给1,最终回溯输出答案。
当然这道题记搜和DFS也都可以,2003年的GDOI应该也是比较简单的一次了吧。时限都是2秒。
代码:
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
const int dx[]={0,-2,-1,1,2,-2,-1,1,2};
const int dy[]={0,-1,-2,-2,-1,1,2,2,1};
int n,state[100001][3],a[101][101],head,tail,sx,sy,ex,ey,father[100001],tot,sum;
string s;
void print(int x,int k) //回溯输出
{
if (father[x]) print(father[x],k);
sum++;
return;
}
bool check(int x,int y)
{
return (x==ex&&y==ey); //到达终点
}
void bfs()
{
father[1]=0;
state[1][1]=sx;
state[1][2]=sy;
head=0;
tail=1; //初始化
do
{
head++;
for (int i=1;i<=8;i++) //8个方向搜索
{
tail++; //入队
int xx=state[head][1]+dx[i];
int yy=state[head][2]+dy[i];
if (xx<1||yy<1||xx>8||yy>8||a[xx][yy]) //不符合要求
{
tail--; //出队
continue;
}
a[xx][yy]=1;
state[tail][1]=xx;
state[tail][2]=yy;
father[tail]=head;
if (check(xx,yy)) //到达了终点
{
sum=0;
print(tail,0);
printf("%d moves\n",sum-1);
return;
}
}
}
while (head<tail);
printf("not reachable\n");
return;
}
int main()
{
while (++tot)
{
scanf("%d",&n);
if (n==-1) break;
for(int i=1;i<=100;i++)
for (int j=1;j<=100;j++) a[i][j]=0;
for (int i=1;i<=n;i++)
{
cin>>s;
a[(int)s[0]-'a'+1][(int)s[1]-'0']=1; //不能走
}
cin>>s;
sx=s[0]-'a'+1;
sy=s[1]-'0';
cin>>s;
ex=s[0]-'a'+1;
ey=s[1]-'0'; //起点和终点
a[sx][sy]=1;
printf("Board %d: ",tot);
bfs();
}
return 0;
}