题目链接:http://poj.org/problem?id=1915
题目大意:给定棋盘边长,起点,终点,问骑士从起点走到终点的最少步数是多少?
分析:双向BFS(程序一般比普通的BFS跑得更快).
写法一(两个辅助队列):
#include<iostream>
#include<map>
#include<string>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define maxn 305
#define whatever 10
int M[maxn][maxn];
struct NODE
{
int x, y;
int step;
}t,U;
int dirs[8][2] = { 1, -2, -1, -2, -2, -1, -2, 1, -1, 2, 1, 2, 2, 1, 2, -1 };
int mark[maxn][maxn];
int bx, by, ex, ey, L;
int now,ans;
void BFS()
{
queue<struct NODE> Q,RQ;
t.x = bx; t.y = by; t.step = 0;
Q.push(t);
t.x = ex; t.y = ey; t.step = 0;
RQ.push(t);
if (bx == ex&&by == ey)
{
ans = 0;
return;
}
mark[bx][by] = 1; mark[ex][ey] = 2;
now = 0;//当前步数
while (!Q.empty() && !RQ.empty())
{
while (!Q.empty() &&Q.front().step == now)
{
U = Q.front(); Q.pop();//出队
for (int i = 0; i < 8; i++)
{
t.x = U.x + dirs[i][0]; t.y = U.y + dirs[i][1]; t.step = U.step + 1;
if (0 <= t.x&&t.x <= L - 1 && 0 <= t.y&&t.y <= L - 1)
if (mark[t.x][t.y] != 1)
{
if (mark[t.x][t.y] == 2)//访问,看看是否访问到从另一端点开始访问的结点
{
ans = now * 2 + 1;
return;
}
Q.push(t);//进队
mark[t.x][t.y] = 1;//置访问标记
}
}
}
while (!RQ.empty()&&RQ.front().step == now)
{
U = RQ.front(); RQ.pop();
for (int i = 0; i < 8; i++)
{
t.x = U.x + dirs[i][0]; t.y = U.y + dirs[i][1]; t.step = U.step + 1;
if (0 <= t.x&&t.x <= L - 1 && 0 <= t.y&&t.y <= L - 1)
if (mark[t.x][t.y] != 2)
{
if (mark[t.x][t.y] == 1)
{
ans = (now+1) * 2;
return;
}
RQ.push(t);
mark[t.x][t.y] = 2;
}
}
}
now++;
}
}
int main()
{
//freopen("f:\\input.txt", "r", stdin);
int i, j, k;
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d", &L);
scanf("%d%d%d%d", &bx, &by, &ex, &ey);
memset(mark, false, sizeof(mark));
BFS();
printf("%d\n", ans);
}
return 0;
}
写法二(一个辅助队列):
#include<iostream>
#include<map>
#include<string>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define maxn 305
#define whatever 10
int M[maxn][maxn];
struct NODE
{
int x, y;
int step;
int note;
}t, U;
int dirs[8][2] = { 1, -2, -1, -2, -2, -1, -2, 1, -1, 2, 1, 2, 2, 1, 2, -1 };
int mark[maxn][maxn];
int bx, by, ex, ey, L;
int now, ans;
void BFS()
{
queue<struct NODE> Q;
t.x = bx; t.y = by; t.step = 0; t.note = 1;
Q.push(t);
t.x = ex; t.y = ey; t.step = 0; t.note = -1;
Q.push(t);
if (bx == ex&&by == ey)
{
ans = 0;
return;
}
mark[bx][by] = 1; mark[ex][ey] = -1;
now = 0;//当前步数
while (!Q.empty())
{
while (!Q.empty())
{
U = Q.front(); Q.pop();//出队
for (int i = 0; i < 8; i++)
{
t.x = U.x + dirs[i][0]; t.y = U.y + dirs[i][1]; t.step = U.step + 1; t.note = U.note;
if (0 <= t.x&&t.x <= L - 1 && 0 <= t.y&&t.y <= L - 1)
if (mark[t.x][t.y] != t.note)
{
if (mark[t.x][t.y] == -t.note)//访问,看看是否访问到从另一端点开始访问的结点
{
ans = t.note == 1 ? (t.step * 2 - 1) : (t.step * 2);
return;
}
Q.push(t);//进队
mark[t.x][t.y] = t.note;//置访问标记
}
}
}
now++;
}
}
int main()
{
//freopen("f:\\input.txt", "r", stdin);
int i, j, k;
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d", &L);
scanf("%d%d%d%d", &bx, &by, &ex, &ey);
memset(mark, false, sizeof(mark));
BFS();
printf("%d\n", ans);
}
return 0;
}