erek1e

IOI '09 P6 - Mecho

Jul 11th, 2023
864
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.51 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4.  
  5. using namespace std;
  6.  
  7. vector<string> g;
  8. vector<vector<bool>> mechoReached, beesReached;
  9. inline bool mechoCanAccess(int i, int j) {
  10.     return g[i][j] != 'T' && !beesReached[i][j];
  11. }
  12. inline bool beesCanAccess(int i, int j) {
  13.     return g[i][j] != 'T' && g[i][j] != 'D';
  14. }
  15. pair<int, int> dir[4]{{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
  16.  
  17. int main() {
  18.     ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  19.     int n, s; cin >> n >> s;
  20.     g.resize(n);
  21.     for (string &row : g) cin >> row;
  22.  
  23.     int mechoStartI, mechoStartJ, mechoEndI, mechoEndJ;
  24.     for (int i = 0; i < n; ++i) {
  25.         for (int j = 0; j < n; ++j) {
  26.             if (g[i][j] == 'M') mechoStartI = i, mechoStartJ = j;
  27.             else if (g[i][j] == 'D') mechoEndI = i, mechoEndJ = j;
  28.         }
  29.     }
  30.  
  31.     auto canWait = [&](int time) -> bool {
  32.         // check if Mecho can wait time seconds
  33.         mechoReached.assign(n, vector<bool>(n, false));
  34.         beesReached.assign(n, vector<bool>(n, false));
  35.         vector<pair<int, int>> beesNew, mechoNew;
  36.         auto inside = [&](int i, int j) {
  37.             return 0 <= i && i < n && 0 <= j && j < n;
  38.         };
  39.        
  40.         bool beesStillChanging = true, mechoStillChanging = true;
  41.         auto moveBees = [&]() {
  42.             vector<pair<int, int>> beesNew2;
  43.             for (auto [i, j] : beesNew) {
  44.                 for (auto [di, dj] : dir) {
  45.                     int ii = i+di, jj = j+dj;
  46.                     if (inside(ii, jj) && !beesReached[ii][jj] && beesCanAccess(ii, jj)) {
  47.                         beesReached[ii][jj] = true;
  48.                         beesNew2.emplace_back(ii, jj);
  49.                     }
  50.                 }
  51.             }
  52.             swap(beesNew, beesNew2);
  53.             if (beesNew.empty()) beesStillChanging = false;
  54.         };
  55.         auto moveMecho = [&]() {
  56.             vector<pair<int, int>> mechoNew2;
  57.             for (auto [i, j] : mechoNew) {
  58.                 if (beesReached[i][j]) continue; // if bees reached after mecho reached
  59.                 for (auto [di, dj] : dir) {
  60.                     int ii = i+di, jj = j+dj;
  61.                     if (inside(ii, jj) && !mechoReached[ii][jj] && mechoCanAccess(ii, jj)) {
  62.                         mechoReached[ii][jj] = true;
  63.                         mechoNew2.emplace_back(ii, jj);
  64.                     }
  65.                 }
  66.             }
  67.             swap(mechoNew, mechoNew2);
  68.             if (mechoNew.empty()) mechoStillChanging = false;
  69.         };
  70.  
  71.         for (int i = 0; i < n; ++i) {
  72.             for (int j = 0; j < n; ++j) {
  73.                 if (g[i][j] == 'H') beesReached[i][j] = true, beesNew.emplace_back(i, j);
  74.             }
  75.         }
  76.         for (int i = 0; i < time; ++i) moveBees();
  77.  
  78.         if (beesReached[mechoStartI][mechoStartJ]) return false;
  79.  
  80.         mechoReached[mechoStartI][mechoStartJ] = true, mechoNew.emplace_back(mechoStartI, mechoStartJ);
  81.         while (mechoStillChanging && !mechoReached[mechoEndI][mechoEndJ]) {
  82.             // move mecho
  83.             for (int i = 0; i < s && mechoStillChanging; ++i) moveMecho();
  84.  
  85.             // move bees
  86.             moveBees();
  87.         }
  88.         return mechoReached[mechoEndI][mechoEndJ];
  89.     };
  90.  
  91.     int left = -1, right = n*n; // binary search on answer
  92.     while (left + 1 < right) {
  93.         int mid = (left + right) / 2;
  94.         // check if Mecho can wait mid seconds
  95.         if (canWait(mid)) left = mid;
  96.         else right = mid;
  97.     }
  98.     cout << left << endl;
  99.     return 0;
  100. }
Advertisement
Add Comment
Please, Sign In to add comment