(搜索,双向BFS)POJ.1915.Knight Moves

题目链接: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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值