HDU 3533 Escape 预处理+bfs

20 篇文章 0 订阅

传送门:HDU3533

题意:

 
 
一个人从(0,0)跑到(n,m),只有k点能量,一秒消耗一点,在图中有k个炮塔,给出炮塔的射击方向c,射击间隔t,子弹速度v,坐标x,y
问这个人能不能安全到达终点
要求: 
1.人不能到达炮塔所在的坐标
2.炮塔会挡住子弹
3.途中遇到子弹是安全的,但是人如果停在这个坐标,而子弹也刚好到这个坐标,人就被射死(即人只会在整数秒死)
4.人可以选择停止不动
思路:先把所有的炮台可以杀死人的坐标点和时间预处理出来,用book[r][c][time]标记,然后对人进行bfs的时候判断一下就好了。
预处理注意点:1.人只有K点能量,因此时间处理到K就好 2.炮塔能挡子弹,因此在炮塔射击方向上遇到另一个炮塔就要停止
3.只有整数时间能杀死人,即从炮塔开始,炮塔射击方向上每过v单位长度就有一个可以杀人的坐标点。
4.人一出发炮塔就开始射击,并且有射击间隔
代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<map>
#define ll long long
#define pi acos(-1)
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>P;
int n,m,d,K;
struct node{
	char dir;
	int t,v,r,c;
}castle[101];
struct path{
	int r,c;
	int time;
};
bool book[101][101][1001],mp[101][101],vis[101][101][1001];
int go[5][2]={0,0,1,0,0,1,-1,0,0,-1};
void init()
{
	int x;
	for(int i=0;i<K;i++)
	{	
		switch (castle[i].dir)
		{
			case 'W':
				x=0;
				for(int j=castle[i].c-1;j>=0;j--)
				if(mp[castle[i].r][j])
				{
					x=j;
					break;
				}
				for(int j=castle[i].c-castle[i].v,t=1;j>=x;j-=castle[i].v,t++)
				for(int k=t;k<=d;k+=castle[i].t)
				book[castle[i].r][j][k]=1;break;
			case 'E':
				x=n;
				for(int j=castle[i].c+1;j<=n;j++)
				if(mp[castle[i].r][j])
				{
					x=j;
					break;
				}
				for(int j=castle[i].c+castle[i].v,t=1;j<=x;j+=castle[i].v,t++)
				for(int k=t;k<=d;k+=castle[i].t)
				book[castle[i].r][j][k]=1;break;
			case 'N':
				x=0;
				for(int j=castle[i].r-1;j>=0;j--)
				if(mp[j][castle[i].c])
				{
					x=j;
					break;
				}
				for(int j=castle[i].r-castle[i].v,t=1;j>=x;j-=castle[i].v,t++)
				for(int k=t;k<=d;k+=castle[i].t)
				book[j][castle[i].c][k]=1;break;
			case 'S':
				x=m;
				for(int j=castle[i].r+1;j<=m;j++)
				if(mp[j][castle[i].c])
				{
					x=j;
					break;
				}
				for(int j=castle[i].r+castle[i].v,t=1;j<=x;j+=castle[i].v,t++)
				for(int k=t;k<=d;k+=castle[i].t)
				book[j][castle[i].c][k]=1;break;
		}
	}
}
void bfs()
{
	queue<path>q;
	while(!q.empty())q.pop();
	q.push({0,0,0});
	memset(vis,false,sizeof(vis));
	vis[0][0][0]=1;
	while(!q.empty())
	{
		path t=q.front(),a;
		if(t.time>=d)
		{
			printf("Bad luck!\n");
			return ;
		}
		if(t.r==m&&t.c==n)
		{
			printf("%d\n",t.time);
			return ;
		}
		q.pop();
		for(int i=0;i<5;i++)
		{
			a.r=t.r+go[i][0];
			a.c=t.c+go[i][1];
			a.time=t.time+1;
			if(a.r<0||a.c<0||a.r>m||a.c>n||vis[a.r][a.c][a.time])continue;
			if(book[a.r][a.c][a.time]||mp[a.r][a.c])continue;
			vis[a.r][a.c][a.time]=1;
			q.push(a);
		}
	}
	printf("Bad luck!\n");
}
int main()
{
	char s[3];
	int t,v;
	while(~scanf("%d%d%d%d",&m,&n,&K,&d))
	{
		memset(mp,0,sizeof(mp));
		memset(book,false,sizeof(book));
		for(int i=0;i<K;i++)
		{
			scanf("%s%d%d%d%d",s,&castle[i].t,&castle[i].v,&castle[i].r,&castle[i].c);
			castle[i].dir=s[0];
			mp[castle[i].r][castle[i].c]=1;
		}
		init();
		if(mp[m][n])
		printf("Bad luck!\n");
		else
		bfs();
	}
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值