POJ 3669: Meteor Shower

http://poj.org/problem?id=3669

题目的大致意思:

1.玩家从原点(0,0)出发

2.有流星在一定时间里往地图上砸。砸到以后,这个点以及上下左右共5个点就再也不能行走了(砸以前可以走)

3.玩家每个单位时间必须要上下左右走一格,只能在第一象限中移动

4.找到最短的行走距离,保证这个点是安全的,即所有流星都不会砸到这个点

 

牵扯到最短距离,首先想到广度搜索

这里要注意一点:题目规定的X,Y是300,但这是流星下落的位置,所以流星的覆盖范围是301(加上 上下左右),那么玩家可以行走到302,所以静态数组至少要开到302以上才行

 

  1 #include <stdio.h>
  2 #include <memory.h>
  3 #include <queue>
  4 using namespace std;
  5 
  6 #define MAX 302        //地图宽度
  7 
  8 int m;    //流星数
  9 int map[MAX][MAX];    //地图
 10 bool visited[MAX][MAX];    //是否访问过
 11 int last;    //最晚的流星时间
 12 
 13 int go[][2] =
 14 {
 15     1, 0,
 16     -1, 0,
 17     0, 1,
 18     0, -1,
 19     0, 0
 20 };    //5个方向
 21 
 22 struct Meteor
 23 {
 24     int x;
 25     int y;
 26     int t;
 27 }meteor[50000];    //流星结构,用于输入
 28 
 29 typedef Meteor Node;    //节点结构,用于bfs
 30 
 31 int max(int a, int b)
 32 {
 33     return a > b ? a : b;
 34 }
 35 
 36 int bfs()
 37 {
 38     memset(visited, false, sizeof(visited));
 39     
 40     queue<Node> q;    //队列
 41 
 42     Node fir;    //起始点入队
 43     fir.x = fir.y = fir.t = 0;
 44     visited[0][0] = true;
 45     
 46     q.push(fir);
 47 
 48     while (q.size() > 0)    //bfs
 49     {
 50         Node now = q.front();
 51         q.pop();
 52 
 53         for (int i = 0; i < 4; i++)    //每次必须行动1格
 54         {
 55             Node tmp = now;
 56             tmp.x += go[i][0];
 57             tmp.y += go[i][1];
 58             tmp.t++;
 59 
 60             if (tmp.x >= 0 && tmp.y >= 0 && map[tmp.x][tmp.y]>tmp.t && !visited[tmp.x][tmp.y])    //没越界、流星还未砸这个格子、还没访问过(重复访问就是不是bfs最优解了)
 61             {
 62                 visited[tmp.x][tmp.y] = true;    //标记
 63                 if (map[tmp.x][tmp.y] > last)    //如果格子不会被砸到
 64                 {
 65                     return tmp.t;
 66                 }
 67                 q.push(tmp);
 68             }
 69         }
 70     }
 71     return -1;
 72 }
 73 
 74 int main()
 75 {
 76     while (scanf("%d", &m) != EOF)
 77     {
 78         for (int i = 0; i < m; i++)
 79         {
 80             scanf("%d %d %d", &meteor[i].x, &meteor[i].y, &meteor[i].t);
 81         }
 82 
 83         memset(map, 0x7f, sizeof(map));    //要严谨一点可以用0x7fffffff,不过就不能用memset了
 84         for (int i = 0; i < m; i++)
 85         {
 86             //计算最晚流星的时间
 87             if (i == 0)
 88                 last = meteor[i].t;
 89             else
 90                 last = max(last, meteor[i].t);
 91 
 92             //更新地图上某个点的最快的流星下落时间
 93             for (int j = 0; j < 5; j++)
 94             {
 95                 int tx = meteor[i].x + go[j][0];
 96                 int ty = meteor[i].y + go[j][1];
 97 
 98                 if (tx >= 0 && ty >= 0 && map[tx][ty]>meteor[i].t)
 99                 {
100                     map[tx][ty] = meteor[i].t;
101                 }
102             }
103         }
104 
105         if (map[0][0] == 0)    //起始点被砸直接gg
106             printf("-1\n");
107         else  //否则bfs
108             printf("%d\n", bfs());
109     }
110     return 0;
111 }

 

posted @ 2015-04-22 10:02  iswoit  阅读(495)  评论(0编辑  收藏  举报