码迷,mamicode.com
首页 > 其他好文 > 详细

P1772 [ZJOI2006]物流运输

时间:2020-01-19 21:58:21      阅读:67      评论:0      收藏:0      [点我收藏+]

标签:访问   bre   代码   include   ini   fine   sdi   main   mes   

思路:

那么思考怎么构建\(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]物流运输

标签:访问   bre   代码   include   ini   fine   sdi   main   mes   

原文地址:https://www.cnblogs.com/zzz-hhh/p/12215674.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!