Codeforces - 1520G-G. To Go Or Not To Go?(全图传送门bfs)

Codeforces - 1520G-G. To Go Or Not To Go?(全图传送门bfs)

 

 

 题目思路:

上篇写了两个图上多传送门的bfs问题

其实多传送门可以看作几个特殊点,因为特殊点的个数比较少,可以从这些特殊点着手

这个题的传送门位置扩大到了全图位置,而且数量上也没有限制

这个题的传送门最多使用一次

假设如果我在ABCD四个点使用两次传送门

分别为A-B,C-D

那么代价为A+B+C+D

所以不如直接A-D

代价为A-D

具体操作:

可以预处理出每个点距离起点和终点的距离,然后可以算出不使用传送门的代价

然后每个点加上自身的权值,代表如果在此处使用传送门,然后找两个最小的就ok了

这里找最小的时候

CODE:

Codeforces - 1520G-G. To Go Or Not To Go?(全图传送门bfs)
// 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

 

上一篇:二维前缀和模板


下一篇:区间DP