[ZJOI2006]物流运输

一开始写状压的的我菜爆了……然后调不过。

后来发现(直接搜索)直接最短路就行了……

\(f[i]\)表示前\(i\)天最少需要多少

\(f[i] = min(f[j] + dis(j + 1, i))\)

然后就好了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
 
const int MAXN = 110;
const int MAXM = 22;
const int INF = 0x3f3f3f3f;
template<typename T>
    inline void getmin(T & x, const T y) { if (x > y) x = y; }
int n, m, K, E, map[MAXM][MAXM];
int t1, t2, t3, cant[MAXN][MAXM], P, f[MAXN];
bool inq[MAXN], cnt[MAXM];
std::queue<int> q;
int dis[MAXM];
int bellman_ford(int b, int e) {
    memset(cnt, 0, sizeof cnt);
    for (int i = b; i <= e; ++i)
        for (int j = 1; j <= m; ++j)
            cnt[j] |= cant[i][j];
    memset(dis, 0x3f, sizeof dis);
    dis[1] = 0; q.push(1); inq[1] = true;
    while (!q.empty()) {
        int t = q.front(); q.pop(); inq[t] = false;
        for (int i = 1; i <= m; ++i) if (!cnt[i])
            if (dis[i] > dis[t] + map[t][i]) {
                dis[i] = dis[t] + map[t][i];
                if (!inq[i]) {
                    inq[i] = true;
                    q.push(i);
                }
            }
    }
    return dis[m];
}
int main() {
    memset(map, 0x3f, sizeof map);
    memset(f, 0x3f, sizeof f); f[0] = 0;
    scanf("%d%d%d%d", &n, &m, &K, &E);
    for (int i = 1; i <= E; ++i) {
        scanf("%d%d%d", &t1, &t2, &t3);
        getmin(map[t1][t2], t3);
        getmin(map[t2][t1], t3);
    }
    scanf("%d", &P);
    while (P --> 0) {
        scanf("%d%d%d", &t1, &t2, &t3);
        for (int i = t2; i <= t3; ++i)
            cant[i][t1] = true;
    }
    for (int i = 1; i <= n; ++i) 
        for (int j = 0, t; j != i; ++j)
            if ((t = bellman_ford(j + 1, i)) != INF)
                getmin(f[i], f[j] + t * (i - j) + K * (j != 0));
    printf("%d\n", f[n]);
    return 0;
}
posted @ 2019-02-11 13:12  daklqw  阅读(113)  评论(0编辑  收藏  举报