AOJ 1178 A Broken Door
解法
前のドワコンの C 問題に似てるということで解いてみました。今回は前回のように二分探索で解くのではなく, ダイクストラっぽく解きたいと思います。
ゴール地点からスタート地点に向かって探索します。ゴール地点からある頂点 (y, x) の距離 d[y][x] がわかっているとすると, (y, x) に隣接する頂点 (ny, nx) について,
・(y, x) から (ny, nx) に普通に行けたらかかるコストは d[y][x] + 1
・(y, x) から (ny, nx) に行けないとすると, 辺 (ny, nx) -> (y, x) は使えないという条件の下での ゴール地点から (ny, nx) への最短距離
となります。最悪の条件では, 上記2つの値の最大値を取れば良いです。これをダイクストラっぽくやります。
const int MAX = 33; const int INF = 1e9; bool ok[MAX][MAX][4]; vector<vi> d[MAX][MAX][4]; vector<vi> bfs(int H, int W) { vector<vi> d(H, vi(W, INF)); queue<pii> que; que.push(pii(H-1, W-1)); d[H-1][W-1] = 0; while (!que.empty()) { auto p = que.front(); que.pop(); int y = p.first, x = p.second; for (int i = 0; i < 4; i++) { if (!ok[y][x][i]) continue; int ny = y+dy[i], nx = x+dx[i]; if (d[ny][nx] > d[y][x]+1) { d[ny][nx] = d[y][x]+1; que.push(pii(ny, nx)); } } } return d; } vector<vi> dijkstra(int H, int W) { vector<vi> ret(H, vi(W, INF)); ret[H-1][W-1] = 0; priority_queue<pair<int, pii> > que; que.push(make_pair(0, pii(H-1, W-1))); while (!que.empty()) { auto p = que.top(); que.pop(); int dist = -p.first; int y = p.second.first, x = p.second.second; if (dist > ret[y][x]) continue; for (int i = 0; i < 4; i++) { if (!ok[y][x][i]) continue; int ny = y+dy[i], nx = x+dx[i]; int tmp = max(dist+1, d[y][x][i][ny][nx]); if (ret[ny][nx] > tmp) { ret[ny][nx] = tmp; que.push(make_pair(-ret[ny][nx], pii(ny, nx))); } } } return ret; } int main() { cin.tie(0); ios::sync_with_stdio(false); int H, W; while (cin >> H >> W) { if (H==0 && W==0) break; memset(ok, false, sizeof(ok)); for (int i = 0; i < H; i++) { for (int j = 0; j < W-1; j++) { int b; cin >> b; if (b == 0) { ok[i][j][0] = true; ok[i][j+1][2] = true; } } if (i < H-1) { for (int j = 0; j < W; j++) { int b; cin >> b; if (b == 0) { ok[i][j][1] = true; ok[i+1][j][3] = true; } } } } vector<vi> d0 = bfs(H, W); for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) { for (int k = 0; k < 4; k++) { if (ok[i][j][k]) { ok[i][j][k] = false; d[i][j][k] = bfs(H, W); ok[i][j][k] = true; } } } vector<vi> ans = dijkstra(H, W); int out = ans[0][0]; if (out >= INF) out = -1; cout << out << endl; } return 0; }