题目思路:
其实多传送门可以看作几个特殊点,因为特殊点的个数比较少,可以从这些特殊点着手
这个题的传送门位置扩大到了全图位置,而且数量上也没有限制
这个题的传送门最多使用一次
假设如果我在ABCD四个点使用两次传送门
分别为A-B,C-D
那么代价为A+B+C+D
所以不如直接A-D
代价为A-D
具体操作:
可以预处理出每个点距离起点和终点的距离,然后可以算出不使用传送门的代价
然后每个点加上自身的权值,代表如果在此处使用传送门,然后找两个最小的就ok了
这里找最小的时候
CODE:
// Problem: G. To Go Or Not To Go? // Contest: Codeforces - Codeforces Round #719 (Div. 3) // URL: https://codeforces.com/contest/1520/problem/G // Memory Limit: 512 MB // Time Limit: 3000 ms // // Powered by CP Editor (https://cpeditor.org) #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <iostream> #include <map> #include <queue> #include <set> #include <sstream> #include <string> #include <vector> using namespace std; typedef long long ll; typedef pair<int, int> PII; typedef unsigned long long ull; const int inf = 0x3f3f3f3f; const long long INF = 1e18; const int maxn = 2e3 + 7; const ll mod = 1e9 + 7; #define pb push_back #define debug(x) cout << #x << ":" << x << endl; #define mst(x, a) memset(x, a, sizeof(x)) #define rep(i, a, b) for (int i = (a); i <= (b); ++i) #define dep(i, a, b) for (int i = (a); i >= (b); --i) inline ll read() { ll x = 0; bool f = 0; char ch = getchar(); while (ch < '0' || '9' < ch) f |= ch == '-', ch = getchar(); while ('0' <= ch && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return f ? -x : x; } void out(ll x) { int stackk[20]; if (x < 0) { putchar('-'); x = -x; } if (!x) { putchar('0'); return; } int top = 0; while (x) stackk[++top] = x % 10, x /= 10; while (top) putchar(stackk[top--] + '0'); } ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans = ans * a % mod; a = a * a % mod; b >>= 1; } return ans; } ll vis[maxn][maxn], n, m, w; ll d1[maxn][maxn], d2[maxn][maxn]; ll a[maxn][maxn]; ll dx[4] = {1, 0, -1, 0}; ll dy[4] = {0, 1, 0, -1}; ll b[maxn * maxn]; void bfs(ll x, ll y, ll d[][maxn]) { queue<PII> q; mst(vis, 0); vis[x][y] = 1; q.push({x, y}); d[x][y] = 0; while (q.size()) { auto fr = q.front(); q.pop(); int x1 = fr.first; int y1 = fr.second; for (int i = 0; i < 4; i++) { int x2 = x1 + dx[i]; int y2 = y1 + dy[i]; if (x2 < 1 || x2 > n || y2 < 1 || y2 > m) continue; if (a[x2][y2] == -1) continue; if (vis[x2][y2] == 0) { vis[x2][y2] = 1; d[x2][y2] = d[x1][y1] + w; q.push({x2, y2}); } } } } ll c[maxn * maxn]; int main() { // ios::sync_with_stdio(false); n = read(), m = read(), w = read(); int cnt = 0; mst(d1, -1); mst(d2, -1); rep(i, 1, n) rep(j, 1, m) a[i][j] = read(); bfs(1, 1, d1), bfs(n, m, d2); ll ans = 1e18; ll res = 0; rep(i, 1, n) rep(j, 1, m) if (a[i][j] >= 0 && d1[i][j] >= 0 && d2[i][j] >= 0) ans = min(ans, d1[i][j] + d2[i][j]); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (a[i][j] > 0) { if (a[i][j] > 0 && d1[i][j] >= 0) b[++cnt] = d1[i][j] + a[i][j]; if (a[i][j] > 0 && d2[i][j] >= 0) c[++res] = d2[i][j] + a[i][j]; } } } sort(b + 1, b + 1 + cnt),sort(c + 1, c + 1 + res); if (cnt && res)ans = min(ans, b[1] + c[1]); if (ans > 1e17)puts("-1"); else out(ans); return 0; } /* */View Code