LuoguP3659 建边 SPFA

链接


传送门

对每一个点(x, y)编号

int make(int x, int y){
    
    
    return (x - 1) * n + y;
}

由于奶牛走3步才休息,而三步中包含走两步和一步的情况,所以我们直接枚举三步,省去加一条和两条边的情况。

const int dx[]={
    
    -2,-1,1,2,2,1,-1,-2,0,1,0,-1,0,3,0,-3};
const int dy[]={
    
    1,2,2,1,-1,-2,-2,-1,1,0,-1,0,3,0,-3,0};

加边

void connect(int x, int y){
    
    
    for (int i = 0; i < 16; ++i) {
    
    
           int nx = x + dx[i];
           int ny = y + dy[i];
            if (nx >= 1 && ny >= 1 && nx <= n && ny <= n){
    
    
                add(make(x, y), make(nx, ny), a[nx][ny] + 3 * t);
        }
    }
}

但是并没有枚举完全,比如说题目给的样例

4 2
30 92 36 10
38 85 60 16
41 13 5 68
20 97 13 80
由5到80只走了两步。
考虑加上特殊边,即走两步或1步可以到达终点。于是补充这些边。

add(make(n - 1, n), make(n, n), t);
    add(make(n, n - 1), make(n, n), t);
    add(make(n - 2, n), make(n, n), t << 1);
    add(make(n, n- 2), make(n, n), t << 1);
    add(make(n - 1, n - 1), make(n, n), t << 1);

code

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

using namespace std;
const int N = 105;
const int M = N * N << 4;
int n, t, cnt;
int a[N][N], vis[N * N], head[M];
long long dis[N * N];
const int dx[]={
    
    -2,-1,1,2,2,1,-1,-2,0,1,0,-1,0,3,0,-3};
const int dy[]={
    
    1,2,2,1,-1,-2,-2,-1,1,0,-1,0,3,0,-3,0};

struct edge{
    
    
    int to, nxt, val;
}e[M];

inline void add(int u, int v, int w){
    
    
    e[++cnt] = {
    
    v, head[u], w};
    head[u] = cnt;
}

int make(int x, int y){
    
    
    return (x - 1) * n + y;
}

void connect(int x, int y){
    
    
    for (int i = 0; i < 16; ++i) {
    
    
           int nx = x + dx[i];
           int ny = y + dy[i];
            if (nx >= 1 && ny >= 1 && nx <= n && ny <= n){
    
    
                add(make(x, y), make(nx, ny), a[nx][ny] + 3 * t);
        }
    }
}

void SPFA(){
    
    
    queue<int> que;
    memset(vis, 0, sizeof vis);
    memset(dis, 0x3f, sizeof dis);
    dis[make(1, 1)] = 0;
    que.push(make(1, 1));
    while (!que.empty()){
    
    
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for (int i = head[u]; i; i = e[i].nxt) {
    
    
            int v = e[i].to;
            if (dis[v] > dis[u] + e[i].val){
    
    
                dis[v] = dis[u] + e[i].val;
                if (!vis[v]) vis[v] = 1, que.push(v);
            }
        }
    }
}

int main(){
    
    
    ios::sync_with_stdio(false);
    cin.tie();
    cin >> n >> t;
    for (int i = 1; i <= n; ++i) {
    
    
        for (int j = 1; j <= n; ++j) {
    
    
            cin >> a[i][j];
        }
    }
    for (int i = 1; i <= n; ++i) {
    
    
        for (int j = 1; j <= n; ++j) {
    
    
            connect(i, j);
        }
    }
    add(make(n - 1, n), make(n, n), t);
    add(make(n, n - 1), make(n, n), t);
    add(make(n - 2, n), make(n, n), t << 1);
    add(make(n, n- 2), make(n, n), t << 1);
    add(make(n - 1, n - 1), make(n, n), t << 1);
    SPFA();
    cout << dis[make(n, n)] << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_50070650/article/details/112781883
今日推荐