题意:
有一个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;
}