結果
問題 | No.2855 Move on Grid |
ユーザー |
|
提出日時 | 2024-08-25 16:11:16 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 898 ms / 3,000 ms |
コード長 | 5,235 bytes |
コンパイル時間 | 1,598 ms |
コンパイル使用メモリ | 135,788 KB |
最終ジャッジ日時 | 2025-02-24 01:44:59 |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 40 |
ソースコード
#include <iostream>#include <string>#include <algorithm>#include <vector>#include <list>#include <set>#include <unordered_set>#include <map>#include <unordered_map>#include <cmath>#include <utility>#include <sstream>#include <queue>#include <queue>using namespace std;vector<int> parent;vector<int> rrank;vector<vector<int>> adj_list;vector<int> distances;using weighted_key = tuple<int, int>;unordered_set<int> visited;priority_queue<weighted_key, vector<weighted_key>, std::greater<>> pqueue;int find_set(int v) {if (v == parent[v])return v;return parent[v] = find_set(parent[v]);}void make_set(int v) {parent[v] = v;rrank[v] = 0;}void union_sets(int a, int b) {a = find_set(a);b = find_set(b);if (a != b) {if (rrank[a] < rrank[b])swap(a, b);parent[b] = a;if (rrank[a] == rrank[b])rrank[a]++;}}bool solve(const vector<vector<int>> &grid, const int k, const int desired_minimum) {int n = grid.size();int m = grid[0].size();for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {make_set(i * m + j);}}vector<pair<int, int>> dirs = {{{-1, 0}, {1, 0}, {0, 1}, {0, -1}}};for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {if (grid[i][j] < desired_minimum) {continue;}int key = i * m + j;for (const auto &d: dirs) {int nexti = i + d.first;int nextj = j + d.second;if (nexti < 0 || nextj < 0 || nexti >= n || nextj >= m) {continue;}if (grid[nexti][nextj] < desired_minimum) {continue;}int nextkey = nexti * m + nextj;union_sets(key, nextkey);}}}// cerr << "components: ";// for (int i = 0; i < n; ++i) {// for (int j = 0; j < m; ++j) {// cerr << "(" << i << "," << j << "): " << find_set(i * m + j) << ", ";// }// }// cerr << endl;for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {adj_list[i * m + j].clear();}}for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {int pcur = find_set(i * m + j);for (const auto &d: dirs) {int nexti = i + d.first;int nextj = j + d.second;if (nexti < 0 || nextj < 0 || nexti >= n || nextj >= m) {continue;}int pnext = find_set(nexti * m + nextj);if (pnext == pcur) {continue;}adj_list[pcur].emplace_back(pnext);adj_list[pnext].emplace_back(pcur);}}}for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {auto &arr = adj_list[i * m + j];std::sort(arr.begin(), arr.end());auto last = std::unique(arr.begin(), arr.end());arr.erase(last, arr.end());}}// find dist from (0,0) to (n-1, m-1)visited.clear();while (!pqueue.empty()) {pqueue.pop();}int start_weight = 0;if (grid[0][0] < desired_minimum) {start_weight = 1;}std::fill(distances.begin(), distances.end(), -1);distances[find_set(0)] = start_weight;pqueue.emplace(start_weight, find_set(0));int target = find_set(n * m - 1);while (!pqueue.empty()) {int cur_dist = std::get<0>(pqueue.top());int cur = std::get<1>(pqueue.top());pqueue.pop();if (visited.find(cur) != visited.end()) {continue;}visited.emplace(cur);if (cur == target) {break;}for (const auto &next: adj_list[cur]) {if (visited.find(next) != visited.end()) {continue;}//cerr << "from " << cur << " can reach " << next << endl;int next_r = next / m;int next_c = next % m;int next_cost = 0;if (grid[next_r][next_c] < desired_minimum) {next_cost += 1;}int next_dist = cur_dist + next_cost;if (distances[next] == -1 || distances[next] > next_dist) {distances[next] = next_dist;pqueue.emplace(next_dist, next);}}}int dist_to_goal = distances[target];// cerr << "num steps to go from (0,0) (comp=" << find_set(0) << ") to (n-1,m-1) (comp=" << target << "): "// << dist_to_goal << endl;bool solvable = dist_to_goal <= k;return solvable;}int main() {ios_base::sync_with_stdio(false);cin.tie(nullptr);int64_t n, m, k;cin >> n >> m >> k;vector<vector<int>> grid(n, vector<int>(m));for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {cin >> grid[i][j];}}parent.resize(n * m);rrank.resize(n * m);adj_list.resize(n * m);distances.resize(n * m);int lo_ans = 0;int hi_ans = 1000000001;while (lo_ans + 1 < hi_ans) {int mid_ans = lo_ans / 2 + hi_ans / 2 + ((lo_ans % 2) + (hi_ans % 2)) / 2;bool solvable = solve(grid, k, mid_ans);// cerr << "Is it solvable at ans=" << mid_ans << "? " << (solvable ? " yes " : " no ") << "(lo=" << lo_ans << ", hi="// << hi_ans << ")" << endl;if (solvable) {// this could be the solution, don't rule it out.lo_ans = mid_ans;} else {// ans must be less than mid_anshi_ans = mid_ans;}}cout << lo_ans << endl;return 0;}