• [ZJOI2006]物流运输


    嘟嘟嘟

    简单说就是一道最短路+dp。

    令dp[i] 表示到第 i 天最小的总成本,每一次 j 从 i 到1枚举,得到dp方程 dp[i] = min(dp[i], dp[j - 1] + cost * (i - j + 1) + k)。其中 cost 表示从 j 到 i 这几天都可以走的最短路,因此在第 j 天要改变一次线路,所以加一次k。这时可定有人会问,若果第 j 天之前和第 j 天开始走的路径是一样的,那不就不应该加k了吗?别忘了,j 是枚举的,因此这个状况会在 j' < j 的时候考虑到。

    然后cost就可以用最短路来求,因为没有负边权,所以用dijkstra就行(坚决不用spfa),然后跑dij的时候判断一下这个港口是否可走就行。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cmath>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<stack>
      9 #include<queue>
     10 #include<vector>
     11 using namespace std;
     12 #define enter puts("")
     13 #define space putchar(' ')
     14 #define Mem(a) memset(a, 0, sizeof(a))
     15 typedef long long ll;
     16 typedef double db;
     17 const int INF = 0x3f3f3f3f;
     18 const db eps  =1e-8;
     19 const int maxn = 25;
     20 const int max_day = 105;
     21 inline ll read()
     22 {
     23     ll ans = 0;
     24     char ch = getchar(), last = ' ';
     25     while(!isdigit(ch)) {last = ch; ch = getchar();}
     26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     27     if(last == '-') ans = -ans;
     28     return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32     if(x < 0) putchar('-'), x = -x;
     33     if(x >= 10) write(x / 10);
     34     putchar(x % 10 + '0');
     35 }
     36 
     37 int n, m, k, e;
     38 vector<int> v[maxn], c[maxn];
     39 bool gg[maxn][max_day];
     40 int dp[max_day];
     41 bool vis[maxn];
     42 
     43 int dis[maxn];
     44 bool in[maxn];
     45 #define pr pair<int, int>
     46 #define mp make_pair
     47 int dijkstra()
     48 {
     49     Mem(in);
     50     for(int i = 1; i <= m; ++i) dis[i] = INF;
     51     priority_queue<pr, vector<pr>, greater<pr> > q;
     52     dis[1] = 0; 
     53     q.push(mp(dis[1], 1));
     54     while(!q.empty())
     55     {
     56         pr node = q.top(); q.pop(); 
     57         int now = node.second;
     58         if(in[now]) continue;
     59         in[now] = 1;
     60         for(int i = 0; i < (int)v[now].size(); ++i)
     61         {
     62             if(vis[v[now][i]]) continue;        //该港口被封锁 
     63             if(dis[now] + c[now][i] < dis[v[now][i]])
     64             {
     65                 dis[v[now][i]] = dis[now] + c[now][i];
     66                 q.push(mp(dis[v[now][i]], v[now][i]));
     67             }
     68         }
     69     }
     70     return dis[m];
     71 }
     72 
     73 int main()
     74 {
     75     n = read(); m = read(); k = read(); e = read();
     76     for(int i = 1; i <= e; ++i)
     77     {
     78         int x = read(), y = read(), co = read();
     79         v[x].push_back(y); c[x].push_back(co);
     80         v[y].push_back(x); c[y].push_back(co);
     81     }
     82     int d = read();
     83     for(int i = 1; i <= d; ++i)
     84     {
     85         int p = read(), L = read(), R = read();
     86         for(int j = L; j <= R; ++j) gg[p][j] = 1;
     87     }
     88     for(int i = 1; i <= n; ++i) dp[i] = INF;
     89     dp[0] = -k;        //第一天不需要换路,但因为dp式式每一次都要换路的,所以dp[0]初值要设为-k 
     90     for(int i = 1; i <= n; ++i)
     91     {
     92         Mem(vis);
     93         for(int j = i; j > 0;--j)
     94         {
     95             for(int w = 1; w <= m; ++w) vis[w] |= gg[w][j];        //注意用 |,就表示有的港口这几天都会被封锁 
     96             int cost = dijkstra();
     97             if(cost == INF) continue;        //可能这几天一条路都走不出来(因为题中只保证一天有路可走) 
     98             dp[i] = min(dp[i], dp[j - 1] + cost * (i - j + 1) + k);
     99         }
    100     }
    101     write(dp[n]); enter;
    102     return 0;
    103 }
    View Code
  • 相关阅读:
    系统生命周期
    系统分析师教程——目录
    企业信息系统——SCM
    企业信息系统——CRM
    .NET 解决方案 核心库整理
    .NET 人工智能相关资料整理
    Task
    正则表达式摘录
    记一次IOS对 JS的支持问题
    JavaScript回顾一下js的基础知识,以及学习一下在项目中了解到的新知识
  • 原文地址:https://www.cnblogs.com/mrclr/p/9492036.html
Copyright © 2020-2023  润新知