P1772 [ZJOI2006]物流运输

Posted zzz-hhh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1772 [ZJOI2006]物流运输相关的知识,希望对你有一定的参考价值。

思路:

那么思考怎么构建(dp)方程
首先我们可以设(f[i])表示前(i)天所花费的最小值
(f[i] = min( f[i],f[j-1]+(i-j+1) ast L+K) (1 leq j leq i))
什么意思呢 ?
就是第(j)天到第(i)天走同一条路,并且这条路和第(j-1)天是不同的
L就是这一天把,l到r天之内不能走的点都去掉,然后跑一边dijkstra
求一下1到m点的最短路,然后跑一下DP式子.
代码中有详解.

code

#include <bits/stdc++.h>
#include <queue>

#define N 100010
#define M 110

using namespace std;
int n, m, e, k, d;
int head[N << 1], add_edge, f[M], dis[M]; bool vis[M];
map<int, bool> ma[M];
struct node {
    int next, to, dis;
}edge[N << 1];
struct OOO {//堆优化dijkstra用品
    int po, dis;
    bool operator < (const OOO &b) const {
        return dis > b.dis;
    }
};

int read() {
    int s = 0, f = 0; char ch = getchar();
    while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    return f ? -s : s;
}

void add(int from, int to, int dis) {//这就是一个很普通的前向星建图
    edge[++add_edge].next = head[from];
    edge[add_edge].to = to;
    edge[add_edge].dis = dis;
    head[from] = add_edge;
}

void dijkstra() {//很普通的堆优化dijkstra
    priority_queue<OOO> q;
    q.push((OOO){1, 0});
    dis[1] = 0;
    while (!q.empty()) {
        OOO fr = q.top(); q.pop();
        int x = fr.po;
        for (int i = head[x]; i; i = edge[i].next) {
            int to = edge[i].to;
            if (!vis[to] && dis[to] > dis[x] + edge[i].dis) {
                dis[to] = dis[x] + edge[i].dis;
                q.push((OOO){to, dis[to]}); 
            }
        }
    }
}

void init(int l) {
    for (int j = 1; j <= m; j++)//判断那个点在这个区间内不能走,然后vis表示访问过了.
        if (ma[j][l]) vis[j] = 1;
    memset(dis, 0x3f, sizeof(dis));//dijkstra用物
}

int main() {
    n = read(), m = read(), k = read(), e = read();
    for (int i = 1, x, y, de; i <= e; i++) {
        x = read(), y = read(), de = read();
        add(x, y, de), add(y, x, de);
    }
    d = read();
    for (int i = 1, dat, l, r; i <= d; i++) {
        dat = read(), l = read(), r = read();
        for (int j = l; j <= r; j++)
            ma[dat][j] = 1;//用map存一下是不是停运的马头
    }
    int ans = 0;
    memset(f, 0x3f, sizeof(f));//dp用物
    f[0] = -k;
    for (int i = 1; i <= n; i++) {
        memset(vis, 0, sizeof(vis));//不清空,火葬场。
        for (int j = i; j >= 1; j--) {
            init(j);
            dijkstra();
            int x = dis[m];
            if (x == 0x3f3f3f3f) break;
            f[i] = min(f[i], f[j - 1] + (i - j + 1) * x + k);//很简单的DP
        }
    }
    cout << f[n];
    return 0;
}

以上是关于P1772 [ZJOI2006]物流运输的主要内容,如果未能解决你的问题,请参考以下文章

[luogu] P1772 [ZJOI2006]物流运输(动态规划,最短路)

P1772 [ZJOI2006]物流运输

P1772 [ZJOI2006]物流运输

P1772 [ZJOI2006]物流运输

洛谷P1772 [ZJOI2006]物流运输

P1772 [ZJOI2006]物流运输 dp+最短路