hdu3553 bfs

题目链接

不是很难的搜索 代码量有点大 细节要注意好 每次打代码量稍微大点的题细节就很容易出问题。

开一个标记三维 如果达到这的时间不同就可以重复这个点,炮弹的话就是每个点枚举四个方向的看有没有炮弹刚好在这就可以了

终点可能有炮弹,这个题因为可以在原地等待 那么在枚举四个方向的时候就可以加一个方向 这个方向就是0,0表示原地不动

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<algorithm>
#include<cmath>
#include<vector>
 
using namespace std;
#define LL long long
struct Castle
{
	int t;
	char dir;
	int v;
}castle[1005];
struct pos
{
	int x;
	int y;
	int t;
};
int dat[105][105];
int n, m, k, d;
int mov[5][2] = { 1,0,0,1,-1,0,0,-1,0,0 };
// vis[x][y][t]标记是否在t时刻到达过x,y 
bool vis[105][105][1005];
bool NoJudgeGo(int mx, int my, int mtime, int dirx, int diry, char ch)
{
	int tx = mx;
	int ty = my;
	// x轴 
	if (dirx != 0)
	{
		while (1)
		{
			tx += dirx;
			if (tx<0 || tx>n)
				return false;
			// 出现炮塔 
			if (dat[tx][ty] != -1)
			{
				Castle tcas = castle[dat[tx][ty]];
				if (tcas.dir == ch)
				{
					if (abs(mx - tx) % tcas.v == 0)
					{
						// 如果达到的时候第一颗炮弹还没到这 
						if (abs(mx - tx) / tcas.v>mtime)
							return false;
						// 我到这的时间减去第一个子弹到这的时间 
						int tem = mtime - abs(mx - tx) / tcas.v;
						// 能整除表示现在有子弹在这 
						if (tem%tcas.t == 0)
							return true;
						return false;
					}
					return false;
				}
				return false;
			}
		}
	}
	// y轴 
	else
	{
		while (1)
		{
			ty += diry;
			if (ty<0 || ty>m)
				return false;
			if (dat[tx][ty] != -1)
			{
				Castle tcas = castle[dat[tx][ty]];
				if (tcas.dir == ch)
				{
					if (abs(my - ty) % tcas.v == 0)
					{
						if (abs(my - ty) / tcas.v>mtime)
							return false;
						// 我到这的时间减去第一个子弹到这的时间 
						int tem = mtime - abs(my - ty) / tcas.v;
						// 能整除表示现在有子弹在这 
						if (tem%tcas.t == 0)
							return true;
						return false;
					}
					return false;
				}
				return false;
			}
		}
	}
	return false;
}
int bfs(int x, int y)
{
	memset(vis, false, sizeof(vis));
	queue<pos>q;
	pos temp;
	temp.x = 0;
	temp.y = 0;
	temp.t = 0;
	q.push(temp);
	while (!q.empty())
	{
		temp = q.front();
		q.pop();
		for (int i = 0; i<5; i++)
		{
			int tx = temp.x + mov[i][0];
			int ty = temp.y + mov[i][1];
			if (tx<0 || ty<0 || tx>n || ty>m || vis[tx][ty][temp.t + 1] || dat[tx][ty] != -1)
				continue;
			// 判断四周是否有朝向我发射的炮弹 
			if (NoJudgeGo(tx, ty, temp.t + 1, -1, 0, 'S') || NoJudgeGo(tx, ty, temp.t + 1, 1, 0, 'N') || NoJudgeGo(tx, ty, temp.t + 1, 0, -1, 'E') || NoJudgeGo(tx, ty, temp.t + 1, 0, 1, 'W'))
			{
				continue;
			}
			if (temp.t + 1>d)
				break;
 
			if (tx == n && ty == m)
			{
				return temp.t + 1;
			}
			pos intemp;
			intemp.t = temp.t + 1;
			intemp.x = tx;
			intemp.y = ty;
			vis[tx][ty][intemp.t] = true;
			q.push(intemp);
		}
	}
	return -1;
}
int main()
{
 
	while (scanf("%d%d%d%d", &n, &m, &k, &d) != EOF)
	{
		memset(dat, -1, sizeof(dat));
		int cas = 0;
		for (int i = 0; i<k; i++)
		{
			getchar();
			int x, y;
			scanf("%c%d%d%d%d", &castle[cas].dir, &castle[i].t, &castle[cas].v, &x, &y);
			dat[x][y] = cas++;
		}
		int ans = bfs(0, 0);
		if (ans == -1)
			printf("Bad luck!\n");
		else
			printf("%d\n", ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值