题目大意:就是给你一个起点和一个终点,按骑士的走法,从起点到终点的最少移动多少次
解题思路:水题~~~直接bfs就可以了,没写过双向bfs,这次训练一下,双向bfs就是用两个队列,一个队列保存从起点开始的状态,另一个保存从终点开始向前搜索的状态,双向bfs主要是区分每个格子是从起点开始搜索到的还是从终点开始搜索到的~每个经过的格子结点保存到达该格子经过的步数,这样两边要是相交了相加就是结果
另外,还可以用A*算法,g函数为走到当前状态的经过的步数,启发函数h为当前格子到终点横坐标差与纵坐标差的和,用优先队列保存每个状态按照g+h排序
双向bfs:
#include
#include
#include
#include
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 que_front;
queue 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)
{
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;
que_front.push(tmp);
}
else
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;
}
A*算法
#include
#include
#include
#include
#include
using namespace std;
struct knight
{
int x,y,step;
int g,h,f;
bool operator < (const knight & k) const
{
return f > k.f;
}
};
int dirs[8][2]={{-2,-1},{-2,1},{2,-1},{2,1},{-1,-2},{-1,2},{1,-2},{1,2}};
int sx, sy, ex, ey;
bool visit[8][8];
int AStar(int x, int y);
inline int Heuristic(const knight &a);
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, 0, sizeof(visit));
int cost = AStar(sx, sy);
printf("To get from %c%d to %c%d takes %d knight moves.\n", y1, x1, y2, x2, cost);
}
return 0;
}
inline int Heuristic(const knight &a)
{
return (abs(a.x - sx) + abs(a.y - sy)) * 10;
}
int AStar(int x, int y)
{
priority_queue que;
knight start;
visit[x][y] = true;
start.x = x;
start.y = y;
start.step = 0;
start.g = 0;
start.h = Heuristic(start);
que.push(start);
while(!que.empty())
{
knight tmp = que.top();
que.pop();
if(tmp.x == ex && tmp.y == ey)
return tmp.step;
knight next;
for(int i = 0; i < 8; i++)
{
next.x = tmp.x + dirs[i][0];
next.y = tmp.y + dirs[i][1];
if(next.x < 0 || next.x >= 8 || next.y < 0 || next.y >= 8 || visit[next.x][next.y])
continue;
visit[next.x][next.y] = true;
next.step = tmp.step + 1;
next.g = tmp.g + 23;
next.h = Heuristic(next);
next.f = next.g + next.h;
que.push(next);
}
}
return -1;
}