ARC003 C - 暗闇帰り道
C: 暗闇帰り道 - AtCoder Regular Contest 003 | AtCoder
- 二分探索 + bfs な問題。
- 以前解いたのにもかかわらず間違えまくった...。
- bfs では pop 直後に vis を見てはじいてしまったり(致命的)、high = 1<<30 から始めたり、val = min(val,pow(0.99,t)*..) を保持しておこうとしたり...無駄なことを。シンプルに書くことを心がけよう。
class C_DarknessWayHome { public: void solve(void) { int N,M; cin>>N>>M; vector<string> field(N); int sx,sy,gx,gy; REP(i,N) { cin>>field[i]; REP(j,M) { if (field[i][j] == 'g') { gx = j; gy = i; } if (field[i][j] == 's') { sx = j; sy = i; } } } const int dx[] = {-1,0,1,0}; const int dy[] = {0,1,0,-1}; // low より明るい状態で goal までたどりつけるか bfs auto bfs = [&](double low) { queue<tuple<int,int,int>> que; que.emplace(sx,sy,0); vector<vector<bool>> vis(N,vector<bool>(M,false)); while ( !que.empty() ) { int x,y,t; tie(x,y,t) = que.front(); que.pop(); REP(d,4) { int nx = x+dx[d]; int ny = y+dy[d]; if (nx < 0 || M <= nx || ny < 0 || N <= ny) continue; if (field[ny][nx] == '#') continue; if (field[ny][nx] == 's') continue; if (field[ny][nx] == 'g') return true; if ( vis[ny][nx] ) continue; double val = pow(0.99,t+1)*(field[ny][nx]-'0'); if (val < low) continue; vis[ny][nx] = true; que.emplace(nx,ny,t+1); } } return false; }; // ゴールに到達しないケースを先にやる if ( !bfs(0.0) ) { cout<<-1<<endl; return; } double low = 0; double high = 10; // fabs(low-high) < EPS の EPS が小さすぎるとループ回数が // 大きくなって TLE してしまうので最大 100 回でやる // // O(100*N*M) REP(i,100) { if (fabs(low-high) < 1e-10) break; double mid = (low+high)*0.5; if ( bfs(mid) ) low = mid; else high = mid; } cout<<setprecision(20)<<low<<endl; } };