--- tags: IOI --- # IOI2009 Day2-2 メッチョ (Mecho) ## 問題 https://www.ioi-jp.org/ioi/2009/problems/day2/Mecho_jp.pdf https://oj.uz/problem/view/IOI09_mecho $N \times N$ マスのフィールドがあり、いくつかの進入不可能なマスと Mecho の家があり、それ以外は草原のマスです。 草原には Mecho がいて、蜂蜜を食べています。 また、いくつかのハチの群れがいて、毎ターン隣接するマスに広がります。 Mecho は毎ターン $S$ マスまで移動できて、ハチと同じマスにならないように家に帰ります。 Mecho が初期位置で蜂蜜を食べ続けることができる最大の時間を求めてください。 $N ≤ 800$ $S ≤ 1000$ ## 考察 スタート時間によってルートが変わってくる / 答えに単調性があるので決め打ち二分探索 `'M'` も草原であることに注意 $O(N^2\log N)$ ## 実装 https://oj.uz/submission/245583 ```cpp #include <bits/stdc++.h> using namespace std; using pii = pair<int, int>; const int INF = 0x3fffffff; const int dx[] = {0, 1, 0, -1}; const int dy[] = {1, 0, -1, 0}; #define name2(a,b,c,...) c #define rep1(b) for(int i = 0; i < b; i++) #define rep2(i,b) for(int i = 0; i < b; i++) #define rep(...) name2(__VA_ARGS__,rep2,rep1)(__VA_ARGS__) #define each(i,a) for(auto&& i : a) template<class T, class U> bool chmin(T& a, const U& b){ if(a > b){ a = b; return 1; } return 0; } template<class T, class U> bool chmax(T& a, const U& b){ if(a < b){ a = b; return 1; } return 0; } int main(){ cin.tie(nullptr); ios::sync_with_stdio(false); int n, s; cin >> n >> s; vector<string> a(n); each(i, a) cin >> i; vector<vector<int>> bee(n, vector<int>(n, INF)); queue<pii> q; rep(n) rep(j, n) if(a[i][j] == 'H'){ bee[i][j] = 0; q.emplace(i, j); } while(q.size()){ auto [x, y] = q.front(); q.pop(); rep(4){ int x2 = x + dx[i], y2 = y + dy[i]; if(x2 < 0 || y2 < 0 || x2 >= n || y2 >= n || a[x2][y2] != 'G' && a[x2][y2] != 'M') continue; if(chmin(bee[x2][y2], bee[x][y] + 1)) q.emplace(x2, y2); } } pii start, goal; rep(n) rep(j, n) if(a[i][j] == 'M') start = {i, j}; rep(n) rep(j, n) if(a[i][j] == 'D') goal = {i, j}; auto check = [&](int v) -> bool { vector<vector<int>> m(n, vector<int>(n, INF)); m[start.first][start.second] = 0; q.push(start); while(q.size()){ auto [x, y] = q.front(); q.pop(); int next = m[x][y] + 1; rep(4){ int x2 = x + dx[i], y2 = y + dy[i]; if(x2 < 0 || y2 < 0 || x2 >= n || y2 >= n || a[x2][y2] == 'T') continue; if(next / s + v < bee[x2][y2] && chmin(m[x2][y2], next)) q.emplace(x2, y2); } } return m[goal.first][goal.second] != INF; }; int ok = -1, ng = bee[start.first][start.second]; while(ng - ok > 1){ int cen = (ok + ng) / 2; if(check(cen)) ok = cen; else ng = cen; } cout << ok << endl; } ```