• [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 }
  • 相关阅读:
    KMP算法
    Java中的字段和属性
    Java的垃圾回收机制
    一个初学所了解的jquery事件
    jQuery选择器
    hide(1000)跟show(1000)
    show/hide
    点击消失功能
    Java中集合Set的用法
    oracle的nvl和sql server的isnull
  • 原文地址:https://www.cnblogs.com/ac-evil/p/10332301.html
Copyright © 2020-2023  润新知