[ZJOI2006]物流运输

题目传送门

这道题的思路应该为$dp$+最短路。

状态设计:

$g[i][j]$表示从第$i$时刻(注意,是时刻)到第$j$时刻过程中不改变路线时的最优解。显然,是将在这期间内所有要关闭的港口从图中删除,然后求最短路。最后乘上$j-i$即可。

$f[i]$表示第$i$时刻的最优解。

状态转移:设之前的第$j$时刻,从第$j$时刻转移到第$i$时刻,要取$f[j]+g[j][i]+K$的最小值。

所以这题得解,时间复杂度为$O(n^2mlogm)$,鉴于本题$n leq 100$、$m leq 20$,该复杂度无压力。

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 #define rep(i, a, b) for (register int i = a; i <= b; ++i)
  6 #define minn(a, b) a = min(a, b);
  7 #define LL long long
  8 
  9 inline int read() {
 10     int w = 0, f = 1; char c = getchar();
 11     while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();
 12     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();
 13     return w * f;
 14 }
 15 
 16 const int maxn = 20 + 5, maxm = 100 + 5;
 17 
 18 struct Edge {
 19     int u, v, w, pre;
 20 };
 21 
 22 struct Node {
 23     int u, d;
 24     bool operator < (const Node &rhs) const {
 25         return d > rhs.d;
 26     }
 27 };
 28 
 29 int n, m, K, e, d, ban[maxn], b[maxm][maxm];
 30 LL f[maxm], g[maxm][maxm];
 31 
 32 priority_queue<Node> q, empty;
 33 
 34 struct Graph {
 35     Edge edges[maxn * maxn << 1];
 36     int n, m;
 37     int G[maxn];
 38     int dis[maxn], vis[maxn];
 39     void init(int n) {
 40         this->n = n;
 41         m = 0;
 42         memset(G, 0, sizeof(G));
 43     }
 44     void Add(int u, int v, int w) {
 45         edges[++m] = (Edge){u, v, w, G[u]};
 46         G[u] = m;
 47     }
 48     int dijkstra() {
 49         memset(dis, 0x3f, sizeof(dis));
 50         rep(i, 1, n) vis[i] = ban[i];
 51         q = empty;
 52         q.push((Node){1, 0});
 53         dis[1] = 0;
 54         while (!q.empty()) {
 55             int u = q.top().u; q.pop();
 56             if (vis[u]) continue;
 57             vis[u] = 1;
 58             for (register int i = G[u]; i; i = edges[i].pre) {
 59                 Edge &e = edges[i];
 60                 if (dis[u] + e.w < dis[e.v]) {
 61                     dis[e.v] = dis[u] + e.w;
 62                     q.push((Node){e.v, dis[e.v]});
 63                 }
 64             }
 65         }
 66         return dis[n];
 67     }
 68 } G;
 69 
 70 int main() {
 71     n = read(), m = read(), K = read(), e = read();
 72     G.init(m);
 73     
 74     rep(i, 1, e) {
 75         int u = read(), v = read(), w = read();
 76         G.Add(u, v, w);
 77         G.Add(v, u, w);
 78     }
 79 
 80     memset(b, 0, sizeof(b));
 81 
 82     d = read();
 83     rep(i, 1, d) {
 84         int P = read(), s = read(), t = read();
 85         rep(x, s, t) b[P][x] = 1;
 86     }
 87 
 88     rep(i, 0, n) {
 89         memset(ban, 0, sizeof(ban));
 90         rep(j, i+1, n) {
 91             rep(k, 1, m) ban[k] |= b[k][j];
 92             g[i][j] = (LL)G.dijkstra() * (j - i);
 93         }
 94     }
 95 
 96     memset(f, 0x3f, sizeof(f));
 97     f[0] = -K;
 98     rep(i, 1, n)
 99         rep(j, 0, i-1)
100             minn(f[i], f[j] + g[j][i] + K);
101     f[0] = 0;
102 
103     printf("%lld", f[n]);
104 
105     return 0;
106 }
原文地址:https://www.cnblogs.com/ac-evil/p/10332301.html