BFS:Meteor Shower(POJ 3669)

                 

                  奔跑吧,傻牛ios

  題目大意:這隻Bessie的牛又要來鬧事了,此次她的任務就是來躲流星雨,流星雨就是在必定時間會從天上砸到Bessie的所在的正方形區域內(Bessie在0,0的位置),而後砸下來後流星雨會把區域內的上下左右區域所有砸爛,而且砸爛後Bessie不能再到這裏,Bessie也不能在流星雨打擊的地方呆着(也就是隻能在流星雨要下來的時間以前才能在這裏),問你Bessie要走多少步才能到安全區域安全

  這一道題好玩,咱們這樣想,Bessie走過的路就是等值的(也就是每走一步都是1),並且還要要求你在矩陣內走,那麼這一題很明顯就是要你用BFS了spa

  可是關鍵的問題是,隕石不是一會兒所有掉落下來的,而是有時間間隔的,那有這麼一個思路,咱們能夠在必定區域時間內看牛能走到哪裏,而後下一波流星雨,毀掉能走掉的部分區域,而後在下一波,這樣咱們只用保存最小的那一些路就能夠了,可是這樣的話顯然是不現實的,由於有時候流星雨砸很長時間,可是一直砸不到某個區域,咱們作的不少工做都是白費的,交題絕對TLE,不要問我爲何知道code

  因此咱們要換一種思路,既然流星雨都會砸下來,那麼咱們爲何不直接先假設讓流星雨先所有砸下來看剩下多少安全區域呢???(這是一種很好的思想,之後會常常用到),可是由於流星雨砸下來是有時間區分的,因此咱們要保留流星雨砸下來的時間,而後從0,0開始BFS,若是BFS所用的步數不足以到達安全區域,那麼就判斷沒法到達,若是能到到安全區域,那麼第一次到達就確定是最短的距離了(BFS的特性),blog

  另外,還要注意,咱們每次掃過位置之後,必定要對位置進行標記,可使用known區域,可是必定要注意,必定要把四個方位區域所有標記上,而不是隻標記出隊的那個點,不這樣作的話,重複會很是多,會TLE,或者直接把map寫上當前最短距離,而後進行判斷就能夠了get

  另一個小問題,原來我一直搞錯了memset的工做原理,原來這玩意是按ANSCII來填字節的。。。。it

  

 1 #include <iostream>
 2 #include <functional>
 3 #include <algorithm>
 4 #include <queue>
 5 #define MAX_N 310
 6 #define MIN(a,b) a<b?a:b
 7 
 8 using namespace std;
 9 
10 void Search(const int);
11 void Inivilize_dir(void);
12 
13 pair<int, int>dir[4];
14 static int dp[MAX_N + 1][MAX_N + 1];
15 static int map[MAX_N + 1][MAX_N + 1];
16 
17 void Inivilize_dir(void)
18 {
19     dir[0].first = -1; dir[0].second = 0;
20     dir[1].first = 1; dir[1].second = 0;
21     dir[2].first = 0; dir[2].second = -1;
22     dir[3].first = 0; dir[3].second = 1;
23 }
24 
25 int main(void)
26 {
27     int M, tx, ty, drop_time,ttx, tty;
28     Inivilize_dir();
29     while (~scanf("%d", &M))
30     {
31         memset(map, -1, sizeof(map));
32 
33         for (int i = 0; i < M; i++)
34         {
35             scanf("%d%d%d", &tx, &ty, &drop_time);
36             if (map[tx][ty] != -1)
37                 map[tx][ty] = MIN(map[tx][ty], drop_time);//最先炸燬時間
38             else map[tx][ty] = drop_time;
39             for (int j = 0; j < 4; j++)//周圍四個點都要
40             {
41                 ttx = tx + dir[j].first;  tty = ty + dir[j].second;
42                 if (ttx >= 0 && ttx <= MAX_N
43                     && tty >= 0 && tty <= MAX_N//座標在矩陣內
44                     )
45                     if (map[ttx][tty] != -1)
46                         map[ttx][tty] = MIN(map[ttx][tty], drop_time);
47                     else map[ttx][tty] = drop_time;
48             }
49         }
50         if (map[0][0] == 0) 
51             cout << -1 << endl;
52         else if (map[0][0] == -1)//開始都打不到還考慮什麼,不動
53             cout << 0 << endl;
54         else Search(M);
55     }
56     return 0;
57 }
58 
59 void Search(const int M)
60 {
61     int ttx, tty, tx, ty;
62     queue<pair<int, int>>que;
63     pair<int, int>tmp, d_tmp;
64     que.push(tmp);
65     while (!que.empty())
66     {
67         tmp = que.front(); que.pop();
68         tx = tmp.first; ty = tmp.second;
69 
70         for (int j = 0; j < 4; j++)
71         {
72             ttx = tx + dir[j].first;  tty = ty + dir[j].second;
73             if (ttx >= 0 && ttx <= MAX_N
74                 && tty >= 0 && tty <= MAX_N//座標在矩陣內
75                 )
76             {
77                 if (map[ttx][tty] == -1)//若是找到安全位置,則更新最短距離
78                 {
79                     cout << dp[tx][ty] + 1 << endl;
80                     return;
81                 }
82                 if (dp[tx][ty] + 1 <= map[ttx][tty] - 1)//若是都比這個時間大,那確定被炸死了
83                 {
84                     dp[ttx][tty] = dp[tx][ty] + 1;
85                     d_tmp.first = ttx; d_tmp.second = tty;
86                     que.push(d_tmp);//還在時間以內,入隊
87                     map[ttx][tty] = dp[ttx][tty];
88                     //不能用known去標記入口,除非是標記全部的點
89                 }
90             }
91         }
92     }
93     cout << -1 << endl;
94 }
相關文章
相關標籤/搜索