我们从广为人知的POJ 2243这道题谈起:题目大意:给定一个起点和一个终点,按骑士的走法(走日字),从起点到终点的最少移动多少次
先看代码:加了注释,然后解释:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct knight
{
int x,y,step;
};
int dir[8][2]={{-2,-1},{-2,1},{2,-1},{2,1},{-1,-2},{-1,2},{1,-2},{1,2}};
int sx, sy, ex, ey;
int visit[8][8];
int color[8][8];
int bfs();
int main()
{
int x1, x2;
char y1, y2;
while(scanf("%c%d %c%d", &y1, &x1, &y2, &x2) != EOF)
{
getchar();
sx = x1 - 1;
sy = y1 - 'a';
ex = x2 - 1;
ey = y2 - 'a';
memset(visit, -1, sizeof(visit));
memset(color, 0, sizeof(color));
int cost = bfs();
printf("To get from %c%d to %c%d takes %d knight moves.\n", y1, x1, y2, x2, cost);
}
return 0;
}
int bfs()
{
if(sx == ex && sy == ey)
return 0;
queue<knight> que_front;//创建队列
queue<knight> que_back;
knight front, back;//结构体
front.x = sx; front.y = sy; front.step = 0;//赋初值
back.x = ex; back.y = ey; back.step = 1;
que_front.push(front);//进队列
que_back.push(back);//进队列
visit[sx][sy] = 0;
visit[ex][ey] = 1;
//由这两个来区分这两个队列
color[sx][sy] = 1;
color[ex][ey] = 2;
int ans1 = 0, ans2 = 0;
while(!que_front.empty() || !que_back.empty())//当两个队列都为空时退出
{
if(!que_front.empty())//队列不空
{
front = que_front.front();//结构体赋值
que_front.pop();//出队列
for(int i = 0; i < 8; i++)
{
int dx = front.x + dir[i][0];
int dy = front.y + dir[i][1];
if(dx >= 0 && dx < 8 && dy >= 0 && dy < 8 && color[dx][dy] != 1)//判断是否被队列1走过
{
if(color[dx][dy] == 0)
{
knight tmp;//建立新结构体,并赋值
tmp.x = dx; tmp.y = dy;
tmp.step = front.step + 1;
visit[dx][dy] = tmp.step;//记录相应步数
color[dx][dy] = 1;//赋队列1的标记值
que_front.push(tmp);//进队列
}
else //即不等于1也不等于0 则肯定是等于2,所以两个相交
return front.step + visit[dx][dy];
}
}
}
if(!que_back.empty())//第二个和第一个同理
{
back = que_back.front();
que_back.pop();
for(int i = 0; i < 8; i++)
{
int dx = back.x + dir[i][0];
int dy = back.y + dir[i][1];
if(dx >= 0 && dx < 8 && dy >= 0 && dy < 8 && color[dx][dy] != 2)
{
if(color[dx][dy] == 0)
{
knight tmp;
tmp.x = dx; tmp.y = dy;
tmp.step = back.step + 1;
visit[dx][dy] = tmp.step;
color[dx][dy] = 2;
que_back.push(tmp);
}
else
return back.step + visit[dx][dy];
}
}
}
}
return -1;//没有路径相通,则返回-1
}
分析:其实其和BFS并没有多大差别,只是它用了两个队列,而其核心部分为1和2的标记,利用标记来判断其是否相交,所有color数组为其能够双向的核心部分,其次visit数组用来记录步数,也是其相连的关键!
综上:要格外注意visit[]和color[]这两个数组,,这是其核心!!!