結果

問題 No.2855 Move on Grid
ユーザー Daniel K
提出日時 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
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

#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_ans
hi_ans = mid_ans;
}
}
cout << lo_ans << endl;
return 0;
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0