zoukankan      html  css  js  c++  java
  • [ZJOI2006]物流运输 DP 最短路

    ~~~题面~~~

    题解:

      设f[i]表示到第i天的代价,cost[i][j]表示第i天到第j天采取同一种方案的最小代价。那么转移就很明显了,直接$n^2$枚举即可。

      所以问题就变成了怎么获取cost数组。因为i到j都采取同一种方案,因此这种方案不能经过在i到j这些天出现故障的码头,因为要求的是最小代价,因此直接跑最短路,然后注意判断一下不能经过在i到j会出现故障的码头即可。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define AC 110
      5 #define ac 450
      6 int n, m, k, e, d;
      7 int Head[AC], date[ac], Next[ac], len[ac], tot;
      8 int dis[AC], f[AC], cost[AC][AC], sum[AC][AC];//sum[天][码头]
      9 bool z[AC];
     10 
     11 struct cmp{
     12     bool operator () (int a, int b)
     13     {
     14         return dis[a] < dis[b];
     15     }
     16 };
     17 
     18 priority_queue<int, vector<int>, cmp> q;
     19 
     20 inline int read()
     21 {
     22     int x = 0;char c = getchar();
     23     while(c > '9' || c < '0') c = getchar();
     24     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
     25     return x;
     26 }
     27 
     28 inline void add(int f, int w, int S)
     29 {
     30     date[++tot] = w, Next[tot] = Head[f], Head[f] = tot, len[tot] = S;
     31     date[++tot] = f, Next[tot] = Head[w], Head[w] = tot, len[tot] = S;
     32 }
     33 
     34 void upmin(int &a, int b)
     35 {
     36     if(b < a) a = b;
     37 }
     38 
     39 void spfa(int l, int r)
     40 {
     41     int x, now;
     42     memset(dis, 127, sizeof(dis));
     43     dis[1] = 0;
     44     q.push(1), z[1] = true;
     45     while(!q.empty())
     46     {
     47         x = q.top();
     48         q.pop();
     49         z[x] = false;
     50         for(R i = Head[x]; i; i = Next[i])
     51         {
     52             now = date[i];
     53             if(sum[r][now] - sum[l - 1][now]) continue;//如果这几天中故障过就不能用
     54             if(dis[now] > dis[x] + len[i])
     55             {
     56                 dis[now] = dis[x] + len[i];
     57                 if(!z[now]) q.push(now), z[now] = true;
     58             }
     59         }
     60     }
     61     if(dis[m] != dis[0]) cost[l][r] = dis[m] * (r - l + 1);
     62     else cost[l][r] = dis[m];//防爆
     63 }
     64 
     65 void pre()
     66 {
     67     int a, b, c;
     68     n = read(), m = read(), k = read(), e = read();
     69     for(R i = 1; i <= e; i ++)
     70     {
     71         a = read(), b = read(), c = read();
     72         add(a, b, c);
     73     }
     74     d = read();
     75     for(R i = 1; i <= d; i ++)
     76     {
     77         a = read(), b = read(), c =read();
     78         for(R j = b; j <= c; j ++) sum[j][a] = 1;
     79     }
     80     for(R i = 1; i <= m; i ++)//枚举码头
     81         for(R j = 1; j <= n; j ++)
     82             sum[j][i] += sum[j - 1][i];
     83 }
     84 
     85 void work()
     86 {
     87     for(R i = 1; i <= n; i ++) 
     88         for(R j = i; j <= n; j ++) spfa(i, j);
     89     memset(f, 127, sizeof(f));
     90     f[0] = -k;//因为第一天不用承受换方案的代价
     91     for(R i = 1; i <= n; i ++)//枚举天数
     92         for(R j = 0; j < i; j ++)//枚举上一段的结尾
     93             upmin(f[i], f[j] + cost[j + 1][i] + k);
     94     printf("%d
    ", f[n]);
     95 }
     96 
     97 int main()
     98 {
     99 //    freopen("in.in", "r", stdin);
    100     pre();
    101     work();
    102 //    fclose(stdin);
    103     return 0;
    104 }
  • 相关阅读:
    cogs 826. [Tyvj Feb11] GF打dota 次短路详细原创讲解! dijkstra
    cogs 2450. 距离 树链剖分求LCA最近公共祖先 快速求树上两点距离 详细讲解 带注释!
    cogs 647. [Youdao2010] 有道搜索框 Trie树 字典树
    cogs 293. [NOI 2000] 单词查找树 Trie树字典树
    P4550 收集邮票
    P1850 换教室 期望dp
    洛谷 UVA11021 Tribles
    P3802 小魔女帕琪 概率与期望
    P3369 【模板】普通平衡树 01Trie树
    P2765 魔术球问题
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9598032.html
Copyright © 2011-2022 走看看