补题记录G. To Go Or Not To Go?
题意:给你一个二维的矩阵,每个点都有一个点权,A要从左上角(1,1)走到右下角(n,m),有如下规则。
1、如果是-1,说明不通,走不了
2、如果是0,说明可以通行
3、如果大于0,说明这是一个传送门,你可以在任意两个传送门之间任意传送,如果你从(i, j)传送到(x, y)那么花费就是\(a_{i, j} + a_{x, y}\)
你可以从任意一个格子走到相邻的合法格子,花费是w,问最后的最小花费是多少。
方法:最短路/BFS
主要还是思维的难度,代码并不难写。首先我们要知道,假如没有传送门就是一道简单的BFS题目。那么加上了这个传送门之后应该如何处理呢?
首先我们想,假如有传送门,我们应该用多少个传送门?
答案:1对就够了
其实很好理解,假如我们要从A传送到B,然后从C传送到D,我们不如直接从A传送到D。所以我们至多只需要一对传送门即可。
那么我们可以预处理出所有传送门到终点的距离,找到最小的那个就是最终我们要传送到的传送门,我们既为best_ed。然后再从起点枚举各个传送门传送到best_ed的距离,取最小值即可。
具体看代码,最后提醒下开long long
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 2010;
inline int lc(int u) {return u << 1;}
inline int rc(int u) {return u << 1 | 1;}
inline int lowbit(int x) {return x & (-x);}
LL a[N][N];
int n, m, w;
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
void bfs(int st, int ed, vector<vector<LL>> &d) {
queue<PII> q;
d[st][ed] = 0;
q.push({st, ed});
while (!q.empty()) {
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i ++ ) {
int x = t.first + dx[i], y = t.second + dy[i];
if (x < 1 || x > n || y < 1 || y > m || d[x][y] != -1 || a[x][y] == -1) continue;
d[x][y] = d[t.first][t.second] + 1;
q.push({x, y});
}
}
}
inline void solve() {
cin >> n >> m >> w;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) cin >> a[i][j];
}
vector<vector<LL>> d1(n + 1, vector<LL> (m + 1, -1));
vector<vector<LL>> d2(n + 1, vector<LL> (m + 1, -1));
bfs(1, 1, d1);
bfs(n, m, d2);
LL best_ed = LLONG_MAX;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
if (d2[i][j] != -1 && a[i][j] >= 1) {
best_ed = min(best_ed, d2[i][j] * w * 1ll + a[i][j]);
}
}
}
LL res = w * 1ll * d1[n][m];
if (d1[n][m] == -1) res = LLONG_MAX;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
if (d1[i][j] != -1 && a[i][j] >= 1 && best_ed != LLONG_MAX) {
res = min(res, w * 1ll * d1[i][j] + a[i][j] + best_ed);
}
}
}
if (res == LLONG_MAX) cout << -1 << endl;
else cout << res << endl;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
// int t; cin >> t;
// while (t -- )
solve();
return 0;
}