Luogu P4009 汽车加油行驶问题

题目链接 \(Click\) \(Here\)

分层图。。好长时间没写差点要忘了\(hhhhh\),其实思路还是很明了的。

注意需要强制消费。

#include <bits/stdc++.h>
using namespace std;

const int N = 110010;
const int M = 550010;
#define int long long

int n, k, A, B, C, have, val[110][110];

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

bool in_map (int x, int y) {
    return 1 <= x && x <= n && 1 <= y && y <= n;
}

int cnt, head[N];

struct edge {
    int nxt, to, w;

    edge (int _nxt = 0, int _to = 0, int _w = 0) {
        nxt = _nxt, to = _to, w = _w;
    }
}e[M];

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

int dis[N];

struct Node {
    int pos, dis;
    bool operator < (Node rhs) const {return dis > rhs.dis;}
    Node (int _pos = 0, int _dis = 0) {pos = _pos, dis = _dis;}
};

priority_queue <Node> q;

int dijkstra (int s, int t) {
    memset (dis, 0x3f, sizeof (dis));
    dis[s] = 0; q.push (Node (s, 0));
    while (!q.empty ()) {
        Node u = q.top (); q.pop ();
        if (dis[u.pos] < u.dis) continue;
        for (int i = head[u.pos]; i; i = e[i].nxt) {
            int v = e[i].to;
            if (dis[v] > dis[u.pos] + e[i].w) {
                dis[v] = dis[u.pos] + e[i].w;
                q.push (Node (v, dis[v]));
            }
        }
    }
    return dis[t];
}

signed main () {
    cin >> n >> k >> A >> B >> C;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            cin >> have;
            val[i][j] = have ? A : A + C;
        }
    }
    int s = node (n, n, k + 1) + 1;
    int t = node (n, n, k + 1) + 2;
    add_edge (s, node (1, 1, 1), 0);
    for (int i = 1; i <= k + 1; ++i) {
        for (int x = 1; x <= n; ++x) {
            for (int y = 1; y <= n; ++y) {
                if (i <= k) {
                    if (i == 1 || val[x][y] != A) {
                        if (in_map (x + 1, y + 0)) add_edge (node (x, y, i), node (x + 1, y + 0, i + 1), 0);
                        if (in_map (x + 0, y + 1)) add_edge (node (x, y, i), node (x + 0, y + 1, i + 1), 0);
                        if (in_map (x - 1, y - 0)) add_edge (node (x, y, i), node (x - 1, y - 0, i + 1), B);
                        if (in_map (x - 0, y - 1)) add_edge (node (x, y, i), node (x - 0, y - 1, i + 1), B);
                    }
                }
                add_edge (node (x, y, i), node (x, y, 1), val[x][y]);
            }
        }
        add_edge (node (n, n, i), t, 0);
    }
    cout << dijkstra (s, t) << endl;
} 

转载于:https://www.cnblogs.com/maomao9173/p/10534932.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值