結果
| 問題 |
No.2855 Move on Grid
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-08-25 15:48:51 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 4,703 bytes |
| コンパイル時間 | 1,488 ms |
| コンパイル使用メモリ | 133,580 KB |
| 最終ジャッジ日時 | 2025-02-24 01:35:41 |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 10 TLE * 1 -- * 29 |
ソースコード
#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<set<int>> adj_list;
vector<int> distances;
void make_set(int v) {
parent[v] = v;
}
int find_set(int v) {
if (v == parent[v])
return v;
return find_set(parent[v]);
}
void union_sets(int a, int b) {
a = find_set(a);
b = find_set(b);
if (a != b)
parent[b] = 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(pnext);
adj_list[pnext].emplace(pcur);
}
}
}
// find dist from (0,0) to (n-1, m-1)
set<int> visited;
using weighted_key = tuple<int, int>;
priority_queue<weighted_key, vector<weighted_key>, std::greater<>> queue;
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;
queue.emplace(start_weight, find_set(0));
int target = find_set(n * m - 1);
while (!queue.empty()) {
int cur_dist = std::get<0>(queue.top());
int cur = std::get<1>(queue.top());
queue.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;
queue.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);
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_ans
hi_ans = mid_ans;
}
}
cout << lo_ans << endl;
return 0;
}