hdu3533 进阶搜索 bfs ESCAPE

该博客探讨了一种地图搜索问题,其中玩家需要避开射箭的堡垒从起点到达终点。难点在于处理箭矢路径的交叉。博主最初尝试预处理堡垒的箭矢路径,但遇到困难,后来改为动态检查当前位置是否存在射箭威胁。代码实现中通过添加额外的else break条件解决了原先的WA(错误)状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意就是在一个m*n的地图上,有k个堡垒,每个堡垒都会想一个固定的方向射箭,现在问你能否在给定的体力下从(0,0)走到(m,n),

分析:其实这题的难点在于如何判定你当前走到的点是否有箭,一开始我想的是预处理,在输入每一个堡垒时,就对它的箭的路线进行标记,但是后来发现这样很难对两个箭相遇时处理,于是就换成了当你走到某一格时,去四个方向找堡垒看看它是否有射向那个点的键以及能否射中。

这个代码一开始总是莫名其妙的wa了,后来加了几个else break 就神奇的过了,哭;

代码:

#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cstdio>

using namespace std;

struct Node
{
	int x, y;
	int enr;
	bool operator <(const Node b)const
	{
		return enr > b.enr;
	}
}node[1010];
struct Cas
{
	int x, y;
	int t, v;
	char di;
}cas[110];
bool vis[110][110][1010];
int map[110][110];
int dir[5][2] = { 1,0,-1,0,0,1,0,-1,0,0 };
int m, n, k, d;

int geth(Node b)//利用了一点a*算法的思想,对其进行预估
{
	return abs(b.x - m) + abs(b.y - n);
}

int check(Node b)
{
	if (b.x < 0 || b.y < 0 || b.x > m || b.y >n)	return 1;
	return 0;
}

void bfs()
{
	priority_queue<Node>que;
	Node a, b;
	vis[0][0][0] = true;
	a.x = a.y = a.enr = 0;
	que.push(a);
	while (!que.empty())
	{
		a = que.top();
		que.pop();
		for (int i = 0; i < 5; i++)
		{
			b = a;
			b.x += dir[i][0];
			b.y += dir[i][1];
			b.enr++;
			if (check(b))	continue;
			if (vis[b.x][b.y][b.enr])	continue;
			if (map[b.x][b.y])	continue;
			if (b.enr + geth(b) > d)	continue;
			int dx,dy;
			int flag = 1;
			dx=b.x-1;
			while (dx >= 0)//向北面找看看有没有往南面射箭的堡垒
			{
				if (map[dx][b.y])
				{
					int c = map[dx][b.y];//获取该堡垒的信息
					int dis = b.x - dx;
					if (cas[c].di == 'S')
					{
						if (dis%cas[c].v == 0)//计算这个点是否是箭的整数点的航行路线上
						{
							int time = dis / cas[c].v;
							if (b.enr == time)
							{
								flag = 0;
								break;
							}
							if (b.enr - time < 0)	break;
							if ((b.enr - time) % cas[c].t == 0)
							{
								flag = 0;
								break;
							}
							else break;
						}
						else break;
					}
					else	break;
				}
				dx--;
			}
			if (!flag)	continue;
			dx = b.x+1;
			while (dx <= m)
			{
				if (map[dx][b.y])
				{
					int c = map[dx][b.y];
					if (cas[c].di != 'N')	break;
					int dis = dx - b.x;
					if (dis%cas[c].v == 0)
					{
						int time = dis / cas[c].v;
						if(b.enr==time)	
						{	
							flag=0;
							break;
						}
						if (b.enr- time < 0)		break;
						if ((b.enr - time) % cas[c].t == 0)
						{
							flag = 0;
							break;
						}
						else break;
					}
					else break;
				}
				dx++;
			}
			if (!flag)	continue;
			dy=b.y+1;
			while (dy <= n)
			{
				if (map[b.x][dy])
				{
					int c = map[b.x][dy];
					if (cas[c].di != 'W')	break;
					int dis = dy - b.y;
					if (dis%cas[c].v == 0)
					{
						int time = dis / cas[c].v;
						if (b.enr == time)
						{
							flag = 0;
							break;
						}
						if (b.enr - time < 0)		break;
						if ((b.enr - time) % cas[c].t == 0)
						{
							flag = 0;
							break;
						}
						else break;
					}
					else break;
				}
				dy++;
			}
			if (!flag)	continue;
			dy = b.y-1;
			while (dy >= 0)
			{
				if (map[b.x][dy])
				{
					int c = map[b.x][dy];
					if (cas[c].di != 'E')	break;
					int dis = b.y - dy;
					if (dis%cas[c].v == 0)
					{
						int time = dis / cas[c].v;
						if (b.enr == time)
						{
							flag = 0;
							break;
						}
						if (b.enr - time < 0)break;
						if ((b.enr - time) % cas[c].t == 0)
						{
							flag = 0;
							break;
						}
						else break;
					}
					else break;
				}
				dy--;
			}
			if (!flag)	continue;
			vis[b.x][b.y][b.enr] = true;
			if (b.x == m && b.y == n)
			{
				printf("%d\n", b.enr);
				return;
			}
			que.push(b);
		}
	}
	printf("Bad luck!\n");
}

int main()
{
		while (scanf("%d %d %d %d", &m, &n, &k, &d) != EOF)
		{
				memset(vis, false, sizeof vis);
				memset(map, 0, sizeof(map));
				for (int i = 1; i <= k; i++)
				{
						int a, b, c, d;
						char e;
						//getchar();
						//scanf("%c %d %d %d %d", &e, &a, &b, &c, &d);
						cin>>e>>a>>b>>c>>d;
						map[c][d] = i;
						cas[i].t = a, cas[i].v = b;
						cas[i].di = e;
				}
				bfs();
		}
		//system("pause");
		return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值