POJ 2384 - Harder Sokoban Problem
http://poj.org/problem?id=2384
概要
N * N のマス目が与えられ,各マスは空白か壁のいずれかである.
プレイヤーは箱を押してゴール地点まで運ぶ. プレイヤーは1ステップで上下左右に動くことができる. 動いた先のマスに箱がある場合,箱を押して進む. ただしプレイヤーも箱も壁のマスには移動できない.
ゴール地点の位置が与えられたとき,ある箱とプレイヤーの初期位置から箱をゴールまで移動させるのに必要な最小ステップ数の最大値を答える.
制約
- 2 <= N <= 25
解法
(箱の位置, プレイヤーの位置) の状態数は 25^4 = 390625 しかない.
ゴールに箱を置いて,その上下左右それぞれにプレイヤーを置いて箱を「ひっぱる」ように BFS して最短経路を求め,その最大値を求める. ただし,箱を一度も押せない場合は無効なので 0 と答えるようにする.
poj/2384.cc1 #include <iostream> 2 #include <vector> 3 #include <queue> 4 #include <algorithm> 5 using namespace std; 6 7 struct state { int i, j, k, l, d; }; 8 9 int main() 10 { 11 int N; 12 cin >> N; 13 vector<string> grid(N); 14 int gi = -100, gj = -100; 15 for (int i = 0; i < N; i++) { 16 cin >> grid[i]; 17 for (int j = 0; j < N; j++) { 18 if (grid[i][j] == '*') { 19 gi = i; 20 gj = j; 21 grid[i][j] = '.'; 22 } 23 } 24 } 25 26 static const int INF = 10000000; 27 static int dist[25][25][25][25]; 28 for (int i = 0; i < N; i++) { 29 for (int j = 0; j < N; j++) { 30 for (int k = 0; k < N; k++) { 31 fill_n(dist[i][j][k], N, INF); 32 } 33 } 34 } 35 queue<state> q; 36 state init; 37 init.i = gi; 38 init.j = gj; 39 init.d = 0; 40 static const int di[] = {-1, 1, 0, 0}, dj[] = {0, 0, -1, 1}; 41 for (int d = 0; d < 4; d++) { 42 init.k = gi - di[d]; 43 init.l = gj - dj[d]; 44 if (0 <= init.k && init.k < N && 0 <= init.l && init.l < N && grid[init.k][init.l] != '#') { 45 dist[init.i][init.j][init.k][init.l] = 0; 46 q.push(init); 47 } 48 } 49 50 int ans = 0; 51 bool valid = false; 52 while (!q.empty()) { 53 const state s = q.front(); 54 q.pop(); 55 ans = max(ans, s.d); 56 57 state t; 58 t.d = s.d + 1; 59 for (int d = 0; d < 4; d++) { 60 const int k = s.k + di[d]; 61 const int l = s.l + dj[d]; 62 if (0 <= k && k < N && 0 <= l && l < N && grid[k][l] != '#' && !(k == s.i && l == s.j)) { 63 if (s.k - di[d] == s.i && s.l - dj[d] == s.j) { 64 // 'push' 65 valid = true; 66 t.i = s.k; 67 t.j = s.l; 68 t.k = k; 69 t.l = l; 70 if (t.d < dist[t.i][t.j][t.k][t.l]) { 71 dist[t.i][t.j][t.k][t.l] = t.d; 72 q.push(t); 73 } 74 } 75 t.i = s.i; 76 t.j = s.j; 77 t.k = k; 78 t.l = l; 79 if (t.d < dist[t.i][t.j][t.k][t.l]) { 80 dist[t.i][t.j][t.k][t.l] = t.d; 81 q.push(t); 82 } 83 } 84 } 85 } 86 cout << (valid ? ans : 0) << endl; 87 88 return 0; 89 }