【HDU - 3533】Escape(bfs)

Escape

 Descriptions:html

一我的從(0,0)跑到(n,m),只有k點能量,一秒消耗一點,在圖中有k個炮塔,給出炮塔的射擊方向c,射擊間隔t,子彈速度v,座標x,y
問這我的能不能安全到達終點
要求: 
1.人不能到達炮塔所在的座標
2.炮塔會擋住子彈
3.途中遇到子彈是安全的,可是人若是停在這個座標,而子彈也恰好到這個座標,人就被射死
4.人能夠選擇中止不動

node

Inputios

對於每一個測試用例,第一行有四個整數,m、n、k和d (2<=m, n<=100, 0<=k<=100, m+ n<=d<=1000)。m和n是戰場的大小,k是城堡的數量,d是A最初擁有的能量單位。接下來的k行分別描述了這些城堡。每一行包含一個字符c和四個整數,t, v, x和y。c是「N」,「S」,「E」或「W」給城堡的發射方向,t, v是子彈的速度(即單位經過每秒),和(x, y)是城堡的位置。這裏咱們假設,若是一座城堡被其餘城堡擊中,它會擋住其餘人的射擊,但不會被摧毀。兩顆子彈會在不影響它們的方向和速度的狀況下擦肩而過。安全

當小A開始逃跑時,全部的城堡都開始射擊。測試

繼續到文件末尾。spa

Output.net

若是小A能逃跑,在一行中輸入其所需的最小秒數。不然,在一行中輸出"Bad luck!"(無需帶引號)code

Sample Inputhtm

4 4 3 10
N 1 1 1 1
W 1 1 3 2
W 2 1 2 4
4 4 3 10
N 1 1 1 1
W 1 1 3 2
W 1 1 2 4

Sample Outputblog

9
Bad luck!

題目連接

https://vjudge.net/problem/HDU-3533

 

其實不難,咱們只須要看當人位於某個點的時候,其四個方向是否有炮塔,這個炮塔是都向人的方向射擊,而後再看子彈是否恰好位於這個座標便可。
而標記的話,vis[x][y][time],對於time時刻,人位於x,y的狀況只須要訪問一次,這是惟一的
 
AC代碼
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #include <sstream>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define Mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define MEM(x,y) memset(x,y,sizeof(x))
#define Maxn 105
using namespace std; int n,m,k,life; int dt[5][2] = {0,1,1,0,0,-1,-1,0,0,0};//四個方向與中止不動的走法
int map[105][105]; bool vis[105][105][1005]; struct period { char c; int t,v; } s[105][105]; struct node { int x,y,step; }; int check(int x,int y) { if(x<0 || x>n || y<0 || y>m) return 1; return 0; } void bfs() { node now,net; queue<node> q; int i,j,flag,dis,timee; now.x = now.y = now.step = 0; q.push(now); vis[0][0][0] = true; while(!q.empty()) { now = q.front(); q.pop(); if(now.step>life) break; if(now.x == n && now.y == m) { cout<<now.step<<endl; return ; } for(i = 0; i<5; i++) { net = now; net.x+=dt[i][0]; net.y+=dt[i][1]; net.step++; if(check(net.x,net.y)) continue; if(!s[net.x][net.y].t && !vis[net.x][net.y][net.step] && net.step<=life)//在符合條件的狀況下,枚舉四個方向
 { flag = 1; for(j = net.x-1; j>=0; j--)//當位於這點,咱們往北向尋找是否有朝南方向射擊的炮臺
 { if(s[j][net.y].t && s[j][net.y].c == 'S')//找到第一個炮臺,且這個炮臺是朝南射擊的
 { dis = net.x-j;//看炮臺與人的距離
                        if(dis%s[j][net.y].v) break;//由於不須要看子彈中途的點,子彈每一秒跑v,距離是dis,dis不能整除v的話,那麼子彈是不可能停在這個點的
                        timee = net.step-dis/s[j][net.y].v;//人走的時間減去第一個子彈飛行到這個位置所需的時間
                        if(timee<0) break;//爲負數就是第一個子彈都沒有通過這個點,那麼人絕對安全
                        if(timee%s[j][net.y].t==0)//看間隔,能整除,那麼就是後續有子彈恰好到這個點,人死定了
 { flag = 0; break; } } if(s[j][net.y].t)//找到炮臺但不是朝南射擊,那麼這個炮臺會當下後面全部子彈,因此北方向安全咱們不須要再找
                        break; } if(!flag)//這個方向都死定了,後面也就不須要看了
                    continue; //其餘方向也是同樣的道理,就不註釋了
                for(j = net.x+1; j<=n; j++) { if(s[j][net.y].t && s[j][net.y].c == 'N') { dis = j-net.x; if(dis%s[j][net.y].v) break; timee = net.step-dis/s[j][net.y].v; if(timee<0) break; if(timee%s[j][net.y].t==0) { flag = 0; break; } } if(s[j][net.y].t) break; } if(!flag) continue; for(j = net.y-1; j>=0; j--) { if(s[net.x][j].t && s[net.x][j].c == 'E') { dis = net.y-j; if(dis%s[net.x][j].v) break; timee = net.step-dis/s[net.x][j].v; if(timee<0) break; if(timee%s[net.x][j].t==0) { flag = 0; break; } } if(s[net.x][j].t) break; } if(!flag) continue; for(j = net.y+1; j<=m; j++) { if(s[net.x][j].t && s[net.x][j].c == 'W') { dis = j-net.y; if(dis%s[net.x][j].v) break; timee = net.step-dis/s[net.x][j].v; if(timee<0) break; if(timee%s[net.x][j].t==0) { flag = 0; break; } } if(s[net.x][j].t) break; } if(!flag) continue; vis[net.x][net.y][net.step] = true; q.push(net); } } } cout<<"Bad luck!"<<endl; } int main() { while(cin>>n>>m>>k>>life) { MEM(vis,0); MEM(s,0); for(int i=0; i<k; i++) { char c; int t,v,x,y; cin>>c>>t>>v>>x>>y; s[x][y].c=c; s[x][y].t=t; s[x][y].v=v; } bfs(); } return 0; }

 

原文出處:https://www.cnblogs.com/sky-stars/p/11218976.html

相關文章
相關標籤/搜索