POJ 2312 - Battle City
http://poj.org/problem?id=2312
概要
M * N のグリッド上で,スタート地点からゴール地点までの最小のステップ数を答える.
各マスは
- Y: スタート地点.
- T: ゴール地点.
- S: 鉄の壁.通れない.撃っても壊せない.
- B: れんがの壁.通れない.一発撃つと壊れて E と等価になる.
- R: 川.通れない.
- E: 空白.通れる.
のいずれか.
1ステップで
- 隣接する4マスに動く
- 四方のいずれかの方向に一発撃つ
のどちらかの行動ができる.
制約
- 2 <= M, N <= 300
解法
れんがの壁は,そのマスを通る直前に壊すことにすれば,B を通るときに2ステップかかると見なしてよい.
よって,単にダイクストラするだけ.
poj/2312.cc1 #include <iostream> 2 #include <vector> 3 #include <queue> 4 using namespace std; 5 6 int main() 7 { 8 int M, N; 9 while (cin >> M >> N && M != 0) { 10 vector<string> grid(M); 11 pair<int,int> start, goal; 12 for (int i = 0; i < M; i++) { 13 cin >> grid[i]; 14 for (int j = 0; j < N; j++) { 15 if (grid[i][j] == 'Y') { 16 start = make_pair(i, j); 17 grid[i][j] = 'E'; 18 } else if (grid[i][j] == 'T') { 19 goal = make_pair(i, j); 20 grid[i][j] = 'E'; 21 } 22 } 23 } 24 25 priority_queue<pair<int, pair<int,int> > > q; 26 static const int INF = 10000000; 27 vector<vector<int> > dist(M, vector<int>(N, INF)); 28 q.push(make_pair(0, start)); 29 dist[start.first][start.second] = 0; 30 while (!q.empty() && q.top().second != goal) { 31 const int c = -q.top().first; 32 const int i = q.top().second.first; 33 const int j = q.top().second.second; 34 q.pop(); 35 if (c > dist[i][j]) { 36 continue; 37 } 38 for (int d = 0; d < 4; d++) { 39 static const int di[] = {-1, 1, 0, 0}, dj[] = {0, 0, -1, 1}; 40 const int k = i + di[d], l = j + dj[d]; 41 if (0 <= k && k < M && 0 <= l && l < N && grid[k][l] != 'R' && grid[k][l] != 'S') { 42 const int cc = dist[i][j] + (grid[k][l] == 'B' ? 2 : 1); 43 if (cc < dist[k][l]) { 44 dist[k][l] = cc; 45 q.push(make_pair(-cc, make_pair(k, l))); 46 } 47 } 48 } 49 } 50 51 if (dist[goal.first][goal.second] == INF) { 52 cout << "-1" << endl; 53 } else { 54 cout << dist[goal.first][goal.second] << endl; 55 } 56 } 57 return 0; 58 }