[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 }