ABC088 D:Grid Repainting
drkenさんによると、「予め盤面をいじるタイプの問題は今後よく出て」くるとのこと。頑張ろう。
https://atcoder.jp/contests/abc088/tasks/abc088_d
経路復元なるものをしなければならないかと思ったが、よく考えればそんなややこしいことをする必要はない。
ゴールにたどり着いた時の最短路 + 1(この1は始点のマス) がそのまま実際に通った白マスの個数になるのだから、あとはこの数値で白マス全体の個数を減らせば、それがそのまま答えとなる。
template <class T>
bool chmin(T &a, T b) {
if (a > b) {
a = b;
return true;
} else {
return false;
}
}
int H, W, N;
vector<vector<char>> g_graph;
vector<vector<int>> g_distance;
const int dy[] = {-1, 0, 0, 1};
const int dx[] = {0, -1, 1, 0};
void bfs(const int gy, const int gx) {
g_distance[0][0] = 0;
queue<P> q;
q.push(P(0, 0));
while (!q.empty()) {
P now = q.front();
q.pop();
int y = now.first, x = now.second;
if (y == gy && x == gx) {
break;
}
rep(i, 4) {
int ny = y + dy[i], nx = x + dx[i];
if (ny < 0 || ny >= H || nx < 0 || nx >= W) {
continue;
}
if (g_graph[ny][nx] == '#') {
continue;
}
if (chmin(g_distance[ny][nx], g_distance[y][x] + 1)) {
q.push(P(ny, nx));
}
}
}
}
signed main() {
cin >> H >> W;
g_graph.assign(H + 10, vector<char>(W + 10));
int white = 0;
rep(i, H) {
rep(j, W) {
char c;
cin >> c;
g_graph[i][j] = c;
if (c == '.') {
white++;
}
}
}
g_distance.assign(H + 10, vector<int>(W + 10, INF));
bfs(H - 1, W - 1);
if (g_distance[H - 1][W - 1] != INF) {
int ans = white - g_distance[H - 1][W - 1] - 1;
cout << ans << endl;
} else {
puts("-1");
}
}
解いた問題数がまだまだ少ないためなんともいえないが、おそらく「予め盤面をいじるタイプの問題」というのは最適解を出しきってからいじってもいいのだろう。