問題E Robot Navigation
解法
BFS(幅優先探索)です。最短距離更新のときにキューに入れるのと経路数の更新をして、最短距離と等しいときは経路数の加算をしています。コード(C++)
#include <iostream> #include <queue> using namespace std; const int dx[4] = {0,1,0,-1}; const int dy[4] = {-1,0,1,0}; const int INF = 1e+8; int h, w, sx, sy, gx, gy, s_dir, ans1, ans2; string c[101]; // d[dir][y][x] := (sx, sy, s_dir) から (x, y, dir)までの最小コスト int d[4][101][101]; // dp[dir][y][x] := (x, y, dir)までの経路数 int dp[4][101][101]; struct State{ int x, y, dir; State(){} State(int x_, int y_, int dir_){ x = x_; y = y_; dir = dir_; } }; void solve(){ for(int i = 0 ; i < 4 ; i++ ){ for(int j = 0 ; j < 101 ; j++ ){ for(int k = 0 ; k < 101 ; k++ ){ d[i][j][k] = INF; dp[i][j][k] = 0; } } } d[s_dir][sy][sx] = 0; dp[s_dir][sy][sx] = 1; queue<State> q; q.push( State(sx, sy, s_dir) ); ans1 = INF, ans2 = 0; while( !q.empty() ){ int x = q.front().x, y = q.front().y, dir = q.front().dir; q.pop(); if( x == gx && y == gy ){ ans1 = d[dir][y][x]; break; } // 右に90度回転 int next_dir = (dir + 1) % 4; if( d[next_dir][y][x] == INF ){ d[next_dir][y][x] = d[dir][y][x] + 1; dp[next_dir][y][x] += dp[dir][y][x] % 1000000; q.push( State(x, y, next_dir) ); }else if( d[dir][y][x] + 1 == d[next_dir][y][x] ){ dp[next_dir][y][x] += dp[dir][y][x] % 1000000; } // 右に90度回転 next_dir = (dir + 3) % 4; if( d[next_dir][y][x] == INF ){ d[next_dir][y][x] = d[dir][y][x] + 1; dp[next_dir][y][x] += dp[dir][y][x] % 1000000; q.push( State(x, y, next_dir) ); }else if( d[dir][y][x] + 1 == d[next_dir][y][x] ){ dp[next_dir][y][x] += dp[dir][y][x] % 1000000; } // 直進する int mx = x, my = y; for( ; true ; ){ mx += dx[dir], my += dy[dir]; if( mx < 0 || my < 0 || w <= mx || h <= my || c[my][mx] == '*' ) break; if( d[dir][my][mx] == INF ){ d[dir][my][mx] = d[dir][y][x] + 1; dp[dir][my][mx] += dp[dir][y][x] % 1000000; q.push( State(mx, my, dir) ); }else if( d[dir][y][x] + 1 == d[dir][my][mx] ){ dp[dir][my][mx] += dp[dir][y][x] % 1000000; } } } for(int i = 0 ; i < 4 ; i++ ){ if( d[i][gy][gx] == ans1 ){ ans2 += dp[i][gy][gx] % 1000000; } } if( ans1 == INF ) ans1 = ans2 = 0; } int main(){ int f[256] = {0}; f['E'] = 1; f['S'] = 2; f['W'] = 3; while( cin >> h >> w , h || w ){ for(int y = 0 ; y < h ; y++ ) cin >> c[y]; for(int y = 0 ; y < h ; y++ ){ for(int x = 0 ; x < w ; x++ ){ if( c[y][x] == '.' || c[y][x] == '*' ) continue; if( c[y][x] == 'X' ){ gx = x, gy = y, c[y][x] = '.'; }else{ sx = x, sy = y, s_dir = f[c[y][x]]; c[y][x] = '.'; } } } solve(); cout << ans1 << " " << ans2 << endl; } }