1. 程式人生 > >【洛谷 P1772】 [ZJOI2006]物流運輸(Spfa,dp)

【洛谷 P1772】 [ZJOI2006]物流運輸(Spfa,dp)

ble href span truct std size con tex urn

題目鏈接
\(g[i][j]\)表示不走在\(i\text{~}j\)時間段中會關閉的港口(哪怕只關\(1\)天)從\(1\)\(m\)的最短路。
\(f[i]\)表示前\(i\)天的最小花費。於是有:
\[f[i]=\min_{j=0}^{i-1}[f[j]+g[i][j]*(i-j)+k]\]
就是枚舉在哪天改計劃。。
邊界\(f[0]=-k\)因為初始計劃不算改。其它均為\(INF\)

#include <cstdio>
#include <queue>
#include <cstring>
#define INF 1000000000
using namespace std;
const int MAXM = 25;
const int MAXN = 110;
const int MAXD = 10010;
inline int read(){
    int s = 0, w = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); }
    return s * w;
}
struct Edge{
    int next, to, dis, id;
}e[MAXN * MAXN << 1];
int head[MAXN], num;
inline void Add(int from, int to, int dis, int id){
    e[++num] = (Edge){ head[from], to, dis, id }; head[from] = num;
    e[++num] = (Edge){ head[to], from, dis, id }; head[to] = num;
}
int n, m, k, t, a, b, c, d, u;
int l[MAXD], r[MAXD], p[MAXD], dis[MAXM], v[MAXM], ban[MAXM], f[MAXN], g[MAXN][MAXN];
queue <int> q;
int main(){
    n = read(); m = read(); k = read(); t = read();
    for(int i = 1; i <= t; ++i){
        a = read(); b = read(); c = read();
        Add(a, b, c, i); 
    }
    d = read();
    for(int i = 1; i <= d; ++i){
        p[i] = read(); l[i] = read(); r[i] = read();
    }
    for(int i = 1; i <= n; ++i)
       for(int j = i; j <= n; ++j){
          for(int o = 2; o <= m; ++o)
             dis[o] = INF, v[o] = ban[o] = 0;
          for(int o = 1; o <= d; ++o)
             if(r[o] >= i && l[o] <= j)
               ban[p[o]] = 1;
          while(q.size()) q.pop();
          q.push(1); 
          while(q.size()){
             u = q.front(); q.pop(); v[u] = 0;
             for(int o = head[u]; o; o = e[o].next)
                if(!ban[e[o].to] && dis[e[o].to] > dis[u] + e[o].dis){
                    dis[e[o].to] = dis[u] + e[o].dis;
                    if(!v[e[o].to]) q.push(e[o].to);
                }
          }
          g[i][j] = dis[m];
       }
    for(int i = 1; i <= n; ++i) f[i] = INF;
    f[0] = -k;
    for(int i = 1; i <= n; ++i)
       for(int j = 0; j < i; ++j)
          f[i] = min(f[i], f[j] + (int)min((long long)INF, (long long)g[j + 1][i] * (i - j)) + k);
    printf("%d\n", f[n]);
    return 0;
}

【洛谷 P1772】 [ZJOI2006]物流運輸(Spfa,dp)