標籤:style blog http color os io for ar
之前的BFS都是需要一個標記數組,但這個題不一樣,因為可能一個格子不止走一次。
那麼我們就要尋找新的入隊條件:left比上次經過的時候大才入隊(left表示上次經過該點時剩餘的時間)。
為什麼呢?我們重複走過一個點只有一個可能,那就是為了去取那個,所以如果取完後再回頭經過這個點的時候剩餘時間變多了,我們的目的就達到了。
left數組初值為0
最佳化:
重設時間的裝置最多取一次就夠了,所以可以再開一個標記數組vis記錄裝置是否用過。
1 //#define LOCAL 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 7 struct Point 8 { 9 int x, y;10 int steps;11 int time;12 }start, end;13 14 int map[10][10], vis[10][10], left[10][10];15 int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};16 int row, col;17 18 void BFS(void)19 {20 queue<Point> qu;21 start.time = 6, start.steps = 0;22 qu.push(start);23 while(!qu.empty())24 {25 Point fir = qu.front();26 qu.pop();27 if(fir.time == 0) continue;28 if(fir.x == end.x && fir.y == end.y)29 {30 printf("%d\n", fir.steps);31 return;32 }33 if(map[fir.x][fir.y] == 4)34 fir.time = 6;35 for(int i = 0; i < 4; ++i)36 {37 int xx = fir.x + dir[i][0];38 int yy = fir.y + dir[i][1];39 if(xx<0 | xx>=row | yy<0 | yy>=col | (!map[xx][yy]))40 continue;41 Point next;42 next.x = xx, next.y = yy;43 next.time = fir.time - 1;44 next.steps = fir.steps + 1;45 if(map[xx][yy] == 4 && vis[xx][yy])46 continue;47 if(next.time > left[xx][yy])48 {49 left[xx][yy] = next.time;50 qu.push(next);51 }52 }53 }54 printf("-1\n");55 }56 57 int main(void)58 {59 #ifdef LOCAL60 freopen("1072in.txt", "r", stdin);61 #endif62 63 int T;64 scanf("%d", &T);65 while(T--)66 {67 scanf("%d%d", &row, &col);68 for(int i = 0; i < row; ++i)69 for(int j = 0; j < col; ++j)70 {71 scanf("%d", &map[i][j]);72 if(map[i][j] == 2)73 start.x = i, start.y = j;74 if(map[i][j] == 3)75 end.x = i, end.y = j;76 }77 memset(vis, 0, sizeof(vis));78 memset(left, 0, sizeof(left));79 BFS();80 }81 return 0;82 }代碼君