Submission #1275104

#TimeUsernameProblemLanguageResultExecution timeMemory
1275104lmduc270410Mecho (IOI09_mecho)C++20
50 / 100
1096 ms4496 KiB
#include <bits/stdc++.h> using namespace std; const int MAXN = 805; const int INF = 1e9; int n, k; string a[MAXN]; int dx[4] = {0,0,-1,1}; int dy[4] = {-1,1,0,0}; int bees_time[MAXN][MAXN]; int sx=-1, sy=-1, tx=-1, ty=-1; // precompute bees_time BFS from all H void compute_bees_time(){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) bees_time[i][j] = INF; queue<pair<int,int>> q; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(a[i][j] == 'H'){ bees_time[i][j] = 0; q.push({i,j}); } if(a[i][j] == 'M'){ sx=i; sy=j; } if(a[i][j] == 'D'){ tx=i; ty=j; } } } while(!q.empty()){ auto cur = q.front(); q.pop(); int x = cur.first, y = cur.second; for(int dir=0; dir<4; ++dir){ int nx = x + dx[dir], ny = y + dy[dir]; if(nx<0||nx>=n||ny<0||ny>=n) continue; if(!(a[nx][ny] == 'G' || a[nx][ny] == 'M')) continue; if(bees_time[nx][ny] == INF){ bees_time[nx][ny] = bees_time[x][y] + 1; q.push({nx, ny}); } } } // bees_time[tx][ty] remains INF (bees don't enter D) } // can(t): Me waits t minutes, then simulate minute-by-minute. Within each minute we do up to k expansions using bitsets. bool can(int t){ if(sx == -1 || tx == -1) return false; if(bees_time[sx][sy] <= t) return false; // bees already at start while waiting // precompute masks per row: // passable_mid: cells Me can occupy/step into during minute (passable and not occupied by bees at start) // passable_end: cells safe at end of minute (passable and bees won't be there at time+1) static bitset<MAXN> passable_mid[MAXN], passable_end[MAXN], passable_all[MAXN]; for(int i=0;i<n;i++){ passable_all[i].reset(); passable_mid[i].reset(); passable_end[i].reset(); for(int j=0;j<n;j++){ bool pass = (a[i][j] == 'G' || a[i][j] == 'M' || a[i][j] == 'D'); if(pass) passable_all[i].set(j); if(pass && bees_time[i][j] > t) passable_mid[i].set(j); // bees not there at start if(pass && bees_time[i][j] > t + 1) passable_end[i].set(j); // safe at end of minute } } // current set of positions (rows of bitsets) static bitset<MAXN> curr[MAXN], visited[MAXN], tmp[MAXN]; for(int i=0;i<n;i++){ curr[i].reset(); visited[i].reset(); tmp[i].reset(); } curr[sx].set(sy); visited[sx].set(sy); int time = t; // if starting at D if(sx == tx && sy == ty) return true; while(true){ // BFS within one minute, multi-source, limited to k steps. // visited_in_min stores all positions reached within <=k steps this minute. for(int i=0;i<n;i++) visited[i] = curr[i]; // start visited = curr bitset<MAXN> layer[MAXN]; for(int i=0;i<n;i++) layer[i] = curr[i]; // if any current position is D, success if(curr[tx].any() && curr[tx].test(ty)) return true; for(int step=0; step<k; ++step){ bool any = false; // compute neighbours of layer (left/right/up/down) respecting passable_mid // tmp = zero for(int r=0;r<n;r++) tmp[r].reset(); for(int r=0;r<n;r++){ if(layer[r].none()) continue; // left/right in same row bitset<MAXN> lr; lr = (layer[r] << 1) | (layer[r] >> 1); lr &= passable_mid[r]; // cannot step into cells that bees occupy at start tmp[r] |= lr; // up if(r > 0){ bitset<MAXN> up = layer[r]; up &= passable_mid[r-1]; tmp[r-1] |= up; } // down if(r+1 < n){ bitset<MAXN> down = layer[r]; down &= passable_mid[r+1]; tmp[r+1] |= down; } } // remove already visited for(int r=0;r<n;r++){ tmp[r] &= (~visited[r]); if(tmp[r].any()) any = true; visited[r] |= tmp[r]; } if(!any) break; // check if reached D in this expansion if(visited[tx].test(ty)) return true; // prepare next layer for(int r=0;r<n;r++) layer[r] = tmp[r]; } // after up-to-k expansions, positions reachable within ≤k steps are in 'visited' // we can only stand at those positions at end of minute if bees_time > time+1 (i.e., passable_end) bool any_next = false; for(int r=0;r<n;r++){ // select safe end positions bitset<MAXN> safe = visited[r] & passable_end[r]; curr[r] = safe; if(curr[r].any()) any_next = true; } if(!any_next) return false; // check if any contains D if(curr[tx].test(ty)) return true; // advance minute time++; // update passable_mid and passable_end for new time for(int i=0;i<n;i++){ // recompute passable_mid: passable and bees_time > time // recompute passable_end: passable and bees_time > time+1 // (we could update incrementally, but recompute is O(n^2/word) per minute; acceptable) passable_mid[i].reset(); passable_end[i].reset(); for(int j=0;j<n;j++){ bool pass = (a[i][j] == 'G' || a[i][j] == 'M' || a[i][j] == 'D'); if(pass && bees_time[i][j] > time) passable_mid[i].set(j); if(pass && bees_time[i][j] > time + 1) passable_end[i].set(j); } } // Also remove from curr any positions that become unsafe at start of next minute: for(int r=0;r<n;r++){ curr[r] &= passable_mid[r]; } // loop continues } return false; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); if(!(cin >> n >> k)) return 0; for(int i=0;i<n;i++) cin >> a[i]; compute_bees_time(); // tighten upper bound: if bees reach start at B, waiting >= B is impossible int upper; if(bees_time[sx][sy] == INF) upper = n * n; else upper = min(n * n, bees_time[sx][sy] - 1); int l = 0, r = upper, ans = -1; while(l <= r){ int mid = (l + r) >> 1; if(can(mid)){ ans = mid; l = mid + 1; } else r = mid - 1; } cout << ans << '\n'; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...