Submission #1143649

#TimeUsernameProblemLanguageResultExecution timeMemory
1143649RufatMecho (IOI09_mecho)C++20
92 / 100
1092 ms17040 KiB
#include <bits/stdc++.h> using namespace std; // A large number used as “infinity” const int INF = 1000000000; // Global direction arrays for 4‐way movement. int dr[4] = {1, -1, 0, 0}; int dc[4] = {0, 0, 1, -1}; // Main int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N, S; cin >> N >> S; vector<string> grid(N); for (int i = 0; i < N; i++){ cin >> grid[i]; } pair<int,int> start, dest; vector<pair<int,int>> hives; // Scan the grid for special cells. for (int i = 0; i < N; i++){ for (int j = 0; j < N; j++){ char c = grid[i][j]; if(c=='M'){ start = {i,j}; } else if(c=='D'){ dest = {i,j}; } else if(c=='H'){ hives.push_back({i,j}); } } } // ------------------------------ // 1. Precompute bees arrival times. // // Bees start at every hive (arrival time 0). // Then, at the end of each minute they “spread” to every adjacent grassy cell. // (Grassy means cells with 'G' or the honeypot cell 'M'.) // Note: The bees do not go into trees ('T') or Mecho’s home ('D'). // ------------------------------ vector<vector<int>> beeTime(N, vector<int>(N, INF)); queue<pair<int,int>> bq; for(auto &h : hives){ int r = h.first, c = h.second; beeTime[r][c] = 0; bq.push({r, c}); } while(!bq.empty()){ auto [r,c] = bq.front(); bq.pop(); int t = beeTime[r][c]; for (int i = 0; i < 4; i++){ int nr = r + dr[i], nc = c + dc[i]; if(nr < 0 || nr >= N || nc < 0 || nc >= N) continue; // Bees only spread into cells that are grassy. if(grid[nr][nc]=='G' || grid[nr][nc]=='M'){ if(beeTime[nr][nc] > t + 1){ beeTime[nr][nc] = t + 1; bq.push({nr, nc}); } } } } // ------------------------------ // 2. Binary search for the maximum number of minutes X that Mecho can wait. // // The idea is to test a candidate waiting time X. // (Recall: if Mecho waits X minutes then at time X he leaves. // During the next moves (each one lasting one minute) he must avoid cells // that “fill up” with bees. In particular, when beginning a move at global time T = X+m, // he may travel (up to S steps) only through cells u with beeTime[u] > T. // If he chooses to “stop” (end his move) in a cell (other than his home D) // then we require beeTime[u] > T+1, because the bees spread after his move.) // ------------------------------ int low = 0; // Mecho must leave from start before bees come in: // so the maximum waiting time is at most beeTime[start]-1. int high = (beeTime[start.first][start.second] == INF ? INF : beeTime[start.first][start.second] - 1); int ans = -1; // This lambda returns true if Mecho can reach D if he waits X minutes. auto canReach = [&](int X) -> bool { // Check that his starting cell is still safe when he starts (global time = X). if(beeTime[start.first][start.second] <= X) return false; // We use a “minute‐level” BFS. // State: (cell, m) where m = number of move–minutes already used. // Global time = X + m. vector<vector<int>> moveTime(N, vector<int>(N, INF)); queue<pair<int,int>> mq; moveTime[start.first][start.second] = 0; mq.push(start); int currentMove = 0; while(!mq.empty()){ // Collect all cells reached at move count = currentMove. vector<pair<int,int>> startCells; int qs = mq.size(); while(qs--){ auto cell = mq.front(); mq.pop(); if(moveTime[cell.first][cell.second] == currentMove) startCells.push_back(cell); } int globalTime = X + currentMove; // time at beginning of this move. // For the current move (lasting one minute), from all startCells, we now determine // the cells that can be reached in at most S steps. // In the movement during the minute, every traversed cell must be safe at time "globalTime", // i.e. beeTime > globalTime. // And if Mecho chooses to “stop” in a cell (landing cell) at the end of the minute, // then (unless it is his home D) that cell must satisfy beeTime > globalTime+1. vector<vector<int>> localDist(N, vector<int>(N, INF)); // steps in current move deque<pair<int,int>> dq; // Initialize multi–source BFS for this move. for(auto &p: startCells){ int r = p.first, c = p.second; if(localDist[r][c] > 0){ localDist[r][c] = 0; dq.push_back({r,c}); } } // nextPositions will hold the cells where Mecho can finish his move. vector<pair<int,int>> nextPositions; while(!dq.empty()){ auto [r,c] = dq.front(); dq.pop_front(); int d = localDist[r][c]; if(d == S) continue; // can’t move further in this minute. for (int i = 0; i < 4; i++){ int nr = r + dr[i], nc = c + dc[i]; if(nr < 0 || nr >= N || nc < 0 || nc >= N) continue; if(localDist[nr][nc] <= d+1) continue; // Mecho cannot walk into obstacles (T or H). if(grid[nr][nc]=='T' || grid[nr][nc]=='H') continue; // For traversal, the cell must be safe at globalTime. if(beeTime[nr][nc] <= globalTime) continue; localDist[nr][nc] = d+1; dq.push_back({nr, nc}); // If he could finish his move here (i.e. “land” here), then: // if the cell is D (home) then bees don’t matter. // Otherwise, we require that beeTime > globalTime+1. if(grid[nr][nc]=='D' || beeTime[nr][nc] > globalTime+1){ // If we haven't reached (nr,nc) in a smaller number of moves, record it. nextPositions.push_back({nr, nc}); } } } // Check if any landing position is the destination. for(auto &p : nextPositions){ if(grid[p.first][p.second]=='D') return true; } // Add all landing positions (if not already reached with fewer moves) to the BFS queue. for(auto &p: nextPositions){ int r = p.first, c = p.second; if(moveTime[r][c] > currentMove + 1){ moveTime[r][c] = currentMove + 1; mq.push({r,c}); } } currentMove++; } return false; }; // Binary search over X. while(low <= high){ int mid = low + (high - low)/2; if(canReach(mid)){ ans = mid; // mid is feasible. low = mid + 1; } else { high = mid - 1; } } cout << ans << "\n"; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...