HDU 3533 Escape(BFS+预处理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3533

题目大意:给你一张n* m的地图,人在起点在(0,0)要到达终点(n,m)有k(k<=100)座炮台,每座炮台都有各自的发射方向、发射周期和发射速度,每隔一段时间会发射一定速度的炮弹,人每秒可以选择停在原地或者往上下左右走,问是否能在时间d之内安全到达终点。如果可以,请输出最短时间。

解题思路:BFS+预处理,分为以下几点:

     ①预处理,用step[x][y][t]记录(x,y)在时间t是否被炮弹打到,这样在bfs时直接判断step就可以了。要注意炮台是可以挡住子弹的(比如从(0,0)到(0,3)如果(0,2)有炮台那就会被挡住,开始没注意半路被炮台挡住,而是只管每秒发射到的点,GG。。。),还有炮台所在地也是不能走的,所以要不要边输入炮台信息边计算step,因为后面输入的炮台可能会档子弹的,输完再预处理。

     ②BFS,要用vis[x][y][t]表示(x,y)这个点在时间t已经走过了,判重,记得要判断(t>lim)是直接返回false,否则会出错(不一定,反正我的会)。

     ③数组记得用bool型,否则会超内存。

代码:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<queue>
  5 #include<string>
  6 using namespace std;
  7 const int N=1e2+5;
  8 
  9 int m,n,k,lim,ans;
 10 int d[6][2]={{-1,0},{1,0},{0,-1},{0,1},{0,0}};
 11 bool attack[N][N][1005];//判断(x,y)在时间t是否被炮台攻击 
 12 bool vis[N][N][1005];//判断t时刻在(x,y) 的状态是否出现过,判重 
 13 
 14 struct node{
 15     int x,y,step;
 16 }pre,now;
 17 
 18 struct node1{
 19     int c,v,t,x,y;
 20 }a[N];
 21 
 22 bool bfs(){
 23     queue<node>q;
 24     now.x=0;
 25     now.y=0;
 26     now.step=0;
 27     q.push(now);
 28     while(!q.empty()){
 29         pre=q.front();
 30         q.pop();
 31         for(int i=0;i<5;i++){        
 32             int xx=pre.x+d[i][0];
 33             int yy=pre.y+d[i][1];
 34             int t=pre.step+1;
 35             //时间不能超过lim 
 36             if(t>lim)
 37                 continue;
 38             if(xx<0||yy<0||xx>n||yy>m)
 39                 continue;
 40             if(vis[xx][yy][t]||attack[xx][yy][t]||attack[xx][yy][0])
 41                 continue;
 42             if(xx==n&&yy==m){
 43                 ans=t;
 44                 return true;
 45             }
 46             vis[xx][yy][t]=true;
 47             now.x=xx;
 48             now.y=yy;
 49             now.step=t;
 50             q.push(now);
 51         }
 52     }
 53     return false;
 54 }
 55 
 56 int main(){
 57     while(~scanf("%d%d%d%d",&n,&m,&k,&lim)){
 58         memset(vis,false,sizeof(vis));
 59         memset(attack,false,sizeof(attack));
 60         for(int i=1;i<=k;i++){            
 61             getchar();
 62             scanf("%c%d%d%d%d",&a[i].c,&a[i].t,&a[i].v,&a[i].x,&a[i].y);
 63             //表示这个位置有炮台 
 64             attack[a[i].x][a[i].y][0]=true;
 65         }
 66         
 67         for(int i=1;i<=k;i++){
 68             char c;
 69             int t,v,x,y;
 70             c=a[i].c,t=a[i].t,v=a[i].v,x=a[i].x,y=a[i].y;
 71             int idx;
 72             if(c=='N')
 73                 idx=0;
 74             if(c=='S')
 75                 idx=1;
 76             if(c=='W')
 77                 idx=2;
 78             if(c=='E')
 79                 idx=3;
 80             int tmp=1;
 81             while(1){
 82                 int xx=x+d[idx][0]*v*tmp;
 83                 int yy=y+d[idx][1]*v*tmp;
 84                 if(xx<0||yy<0||xx>n||yy>m)
 85                     break;
 86                 bool flag=false;
 87                 //判断中途是否有炮台挡住子弹 
 88                 for(int j=1+v*(tmp-1);j<=v*tmp;j++){
 89                     int tx=x+d[idx][0]*j;
 90                     int ty=y+d[idx][1]*j;
 91                     if(attack[tx][ty][0]){
 92                         flag=true;
 93                         break;
 94                     }
 95                 }
 96                 if(flag)
 97                     break;
 98                 //根据周期,计算被子弹攻击的时间 
 99                 int tt=tmp;    
100                 while(tt<=1000){
101                     attack[xx][yy][tt]=true;
102                     tt+=t;
103                 }
104                 tmp++;
105             }    
106         }
107         if(bfs())
108             printf("%d
",ans);
109         else
110             puts("Bad luck!");
111     }
112     return 0;
113 }
原文地址:https://www.cnblogs.com/fu3638/p/7542682.html