欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

BZOJ2143: 飞飞侠 最短路

程序员文章站 2022-05-22 13:35:39
...

Description
给出两个 n ∗ m 的矩阵 A,B,以及 3 个人的坐标
在 (i, j) 支付 Ai,j 的费用可以弹射到曼哈顿距离不超过 Bi,j 的位置
问三个人汇合所需要的最小总费用


Sample Input
4 4
0 0 0 0
1 2 2 0
0 2 2 1
0 0 0 0
5 5 5 5
5 5 5 5
5 5 5 5
5 5 5 5
2 1 3 4 2 2


Sample Output
Z
15


首先考虑做最短路,但太大了,搞不了啊(*&¥%……)
膜了发题解,竟然设三维来dij。心态大崩,什么时候我连这种东西都忘了
然后就搞了一会儿???
信息室老爷机跑了14s,AC了,嗯。。。


#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
int _min(int x, int y) {return x < y ? x : y;}
int _max(int x, int y) {return x > y ? x : y;}
const int dx[5] = {0, 0, 1, 0, -1};
const int dy[5] = {0, 1, 0, -1, 0};

struct node {
    int x, y, k, d;
    friend bool operator < (node a, node b) {return a.d > b.d;}
}; priority_queue<node> q;
int f[160][160][310];
int a[160][160], b[160][160];
int hh[3][160][160];
bool v[160][160][310];
int X[3], Y[3];

int main() {
    int n, m; scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) {
        scanf("%d", &a[i][j]);
        a[i][j] = _min(a[i][j], _max(n - i, i - 1) + _max(m - j, j - 1));
    }
    for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) scanf("%d", &b[i][j]);
    scanf("%d%d%d%d%d%d", &X[0], &Y[0], &X[1], &Y[1], &X[2], &Y[2]);
    for(int p = 0; p < 3; p++) {
        int sx = X[p], sy = Y[p];
        node tmp; tmp.x = sx, tmp.y = sy;
        tmp.k = a[sx][sy], tmp.d = b[sx][sy];
        while(!q.empty()) q.pop();
        q.push(tmp);
        memset(f, 63, sizeof(f)); f[sx][sy][a[sx][sy]] = b[sx][sy]; f[sx][sy][0] = 0;
        memset(v, 0, sizeof(v)); v[sx][sy][0] = 1;
        int u1 = (p - 1 + 3) % 3, u2 = (p + 1) % 3;
        while(!q.empty() && (!v[X[u1]][Y[u1]][0] || !v[X[u2]][Y[u2]][0])) {
            node now = q.top(); q.pop();
            int x = now.x, y = now.y;
            if(v[x][y][now.k]) continue; v[x][y][now.k] = 1;
            for(int k = 0; k < 5; k++) {
                int nx = x + dx[k], ny = y + dy[k];
                if(nx <= 0 || ny <= 0 || nx > n || ny > m) continue;
                if(now.k == 0) {
                    if(f[x][y][a[x][y]] > f[x][y][0] + b[x][y]) {
                        f[x][y][a[x][y]] = f[x][y][0] + b[x][y];
                        tmp.x = x, tmp.y = y;
                        tmp.k = a[x][y], tmp.d = f[x][y][a[x][y]];
                        q.push(tmp);
                    }
                } else {
                    if(f[nx][ny][now.k - 1] > f[x][y][now.k] && !v[nx][ny][now.k - 1]) {
                        f[nx][ny][now.k - 1] = f[x][y][now.k];
                        tmp.x = nx, tmp.y = ny;
                        tmp.k = now.k - 1, tmp.d = f[nx][ny][now.k - 1];
                        q.push(tmp);
                    }
                } if(now.k == 0) break;
            }
        }
        for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) hh[p][i][j] = f[i][j][0];
    } int ans = 999999999, k;
    if(hh[1][X[0]][Y[0]] + hh[2][X[0]][Y[0]] < ans) ans = hh[1][X[0]][Y[0]] + hh[2][X[0]][Y[0]], k = 0;
    if(hh[0][X[1]][Y[1]] + hh[2][X[1]][Y[1]] < ans) ans = hh[0][X[1]][Y[1]] + hh[2][X[1]][Y[1]], k = 1;
    if(hh[0][X[2]][Y[2]] + hh[1][X[2]][Y[2]] < ans) ans = hh[0][X[2]][Y[2]] + hh[1][X[2]][Y[2]], k = 2;
    if(ans == 999999999) {printf("NO\n"); return 0;}
    else {
        printf("%c\n", 'X' + k);
        printf("%d\n", ans);
    }
    return 0;
}
相关标签: 最短路