HDU-3533

题意:

有一个n+1*m+1大小的图,在这个图上有一些炮台,这些炮台会每隔一段时间就射出一发子弹,不同的炮台射出的子弹速度也不一样,人从(0,0)出发到(n,m),如果能量耗尽或被子弹射到就算结束,求到达目标点的最短时间。

要点:

1、只有当人和子弹同时到达同一点时,人才算被射中,否则即使人穿过子弹也没事。

2、子弹打到炮台或飞出去会消失。

3、射击间隔为1的炮台在人的每一次行动都会射出一发子弹,射击间隔为1的炮台在人的每两次行动会射出一发子弹,以此类推。

4、输入数据中炮台的坐标是(t,v,y.x),而不是题目给出的(t,v,x,y)。

5、人可以在原地等待。

思路:

用广搜来解决,再用优先队列保证节点的时间是非递减的,这样就能够对地图进行模拟,写一个update函数,每次时间增加时就模拟下一秒的情况并写入地图,但其实也可以在人每走一步时就查找横纵方向上有没有炮台能够射击到人,这样就不用模拟。然后有一个重要的剪枝,因为人不会在原地等待超过两秒,如果超过两秒就说明要走的那个方向上会一直有子弹,所以可以开一个100*100*3的数组来判重。此外我还加了一个曼哈顿距离的剪枝。


#include <iostream>
#include <queue>
#include <string.h>
using namespace std;

struct qnode{
	int x,y,t,flag;
	bool operator < (const qnode &a) const{
		return t>a.t;
	}
};

struct node{
	int t,v,x,y,shot;
	char c;
	queue<qnode> bullet;
};

int n,m,k,d,time;
int value[5][2] = {{1,0},{-1,0},{0,1},{0,-1},{0,0}};
int map[105][105];
bool flag[105][105][3];
node castle[105];

void updata(int t){
	if(t<=time) return;
	time = t;
	int i,j;
	qnode temp;
	queue<qnode> q;
	memset(map,0,sizeof(map));
	for(i=0;i<k;i++) map[castle[i].y][castle[i].x] = 1;
	for(i=0;i<k;i++){
		while(!castle[i].bullet.empty()){
			temp = castle[i].bullet.front();
			switch(castle[i].c){
				case 'N':{temp.x = castle[i].x; temp.y = castle[i].y-castle[i].v*(time-temp.t); break;}
				case 'S':{temp.x = castle[i].x; temp.y = castle[i].y+castle[i].v*(time-temp.t); break;}
				case 'E':{temp.x = castle[i].x+castle[i].v*(time-temp.t); temp.y = castle[i].y; break;}
				case 'W':{temp.x = castle[i].x-castle[i].v*(time-temp.t); temp.y = castle[i].y; break;}
			}
			if(temp.x>=0 && temp.x<=n && temp.y>=0 && temp.y<=m){
				if(temp.x == castle[i].x){
					if(temp.y>castle[i].y){
						for(j=castle[i].y+1;j<=temp.y;j++){
							if(map[j][temp.x] != 0) break;
						}
						if(j != temp.y+1) castle[i].bullet.pop();
						else break;
					}
					else{
						for(j=temp.y;j<castle[i].y;j++){
							if(map[j][temp.x] != 0) break;
						}
						if(j != castle[i].y) castle[i].bullet.pop();
						else break;
					}
				}
				else{
					if(temp.x>castle[i].x){
						for(j=castle[i].x+1;j<=temp.x;j++){
							if(map[temp.y][j] != 0) break;
						}
						if(j != temp.x+1) castle[i].bullet.pop();
						else break;
					}
					else{
						for(j=temp.x;j<castle[i].x;j++){
							if(map[temp.y][j] != 0) break;
						}
						if(j != castle[i].x) castle[i].bullet.pop();
						else break;
					}
				}
			}
			else castle[i].bullet.pop();
		}
	}
	for(i=0;i<k;i++){
		castle[i].shot--;
		if(castle[i].shot == 0){
			switch(castle[i].c){
			case 'N':{temp.x = castle[i].x; temp.y = castle[i].y; break;}
			case 'S':{temp.x = castle[i].x; temp.y = castle[i].y; break;}
			case 'E':{temp.x = castle[i].x; temp.y = castle[i].y; break;}
			case 'W':{temp.x = castle[i].x; temp.y = castle[i].y; break;}
			}
			temp.t = time;
			castle[i].bullet.push(temp);
			castle[i].shot = castle[i].t;
		}
	}
	for(i=0;i<k;i++){
		while(!castle[i].bullet.empty()){
			temp = castle[i].bullet.front();
			q.push(temp);
			switch(castle[i].c){
				case 'N':{temp.x = castle[i].x; temp.y = castle[i].y-castle[i].v*(time-temp.t); break;}
				case 'S':{temp.x = castle[i].x; temp.y = castle[i].y+castle[i].v*(time-temp.t); break;}
				case 'E':{temp.x = castle[i].x+castle[i].v*(time-temp.t); temp.y = castle[i].y; break;}
				case 'W':{temp.x = castle[i].x-castle[i].v*(time-temp.t); temp.y = castle[i].y; break;}
			}
			map[temp.y][temp.x] = 1;
			castle[i].bullet.pop();
		}
		while(!q.empty()){
			castle[i].bullet.push(q.front());
			q.pop();
		}
	}
}

int BFS(){
	priority_queue<qnode> q;
	qnode temp1,temp2;
	temp1.x = 0;
	temp1.y = 0;
	temp1.t = 0;
	temp1.flag = 2;
	flag[temp1.y][temp1.x][temp1.flag] = 1;
	q.push(temp1);
	while(!q.empty()){
		temp1 = q.top();
		q.pop();
		for(int i=0;i<5;i++){
			temp2.x = temp1.x + value[i][0];
			temp2.y = temp1.y + value[i][1];
			temp2.t = temp1.t+1;
			temp2.flag = temp1.flag;
			if(i == 4 && temp2.flag == 0) continue;
			if(i == 4) temp2.flag--;
			else temp2.flag = 2;
			updata(temp2.t);
			if(temp2.x>=0 && temp2.x<=n && temp2.y>=0 && temp2.y<=m && map[temp2.y][temp2.x] == 0){
				if(temp2.x == n && temp2.y == m) return temp2.t;
				if(n-temp2.x+m-temp2.y<=d-temp2.t){
					if(flag[temp2.y][temp2.x][temp2.flag]) continue;
					flag[temp2.y][temp2.x][temp2.flag] = 1;
					q.push(temp2);
				}
			}
		}
	}
	return -1;
}

int main(){
	int i,temp;
	qnode b;
	while(cin>>m>>n>>k>>d){
		for(i=0;i<k;i++){
			cin>>castle[i].c>>castle[i].t>>castle[i].v>>castle[i].y>>castle[i].x;
			while(!castle[i].bullet.empty()) castle[i].bullet.pop();
			b.x = castle[i].x;
			b.y = castle[i].y;
			b.t = 0;
			castle[i].bullet.push(b);
			castle[i].shot = castle[i].t;
		}
		memset(flag,0,sizeof(flag));
		time = 0;
		temp = BFS();
		if(temp == -1) cout<<"Bad luck!"<<endl;
		else cout<<temp<<endl;
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值