BZOJ1003

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
#define maxn 3005
#define rint register int
#define ll long long
#define int unsigned long long
#define inf 0x77777777777777f
#define pb push_back
#define mod (int)1e9 + 7
using namespace std;
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
inline void write(int x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
    return ;
}

int n, m, K, e, dp[maxn];
int d, stop[maxn][maxn], cost[maxn][maxn]; //cost[i][j]表示第i到j天不变路线的单次最少花费 
int dis[maxn], vis[maxn], no[maxn]; queue<int> q;
int head[maxn], nex[maxn], to[maxn], val[maxn], total;
inline void add(int a, int b, int c)
{
    to[++total] = b, nex[total] = head[a], head[a] = total, val[total] = c;
    return ;
} 

inline int spfa(int x, int y)
{
    memset(dis, 0x3f, sizeof(dis)), memset(vis, 0, sizeof(vis)), memset(no, 0, sizeof(no));
    for (rint i = 1; i <= m; ++i)
      for (rint j = x; j <= y; ++j)
        if (stop[i][j]) no[i] = 1;
    dis[1] = 0, vis[1] = 1, q.push(1);
    while (!q.empty())
    {
        int u = q.front(); q.pop();
        for (rint e = head[u]; e; e = nex[e])
        {
            int v = to[e];
            if (!no[v] && dis[v] > dis[u] + val[e])
            {
                dis[v] = dis[u] + val[e];
                if (!vis[v])
                {
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
        vis[u] = 0;
    }
    return dis[m];
}

signed main()
{
    n = read(), m = read(), K = read(), e = read();
    for (rint i = 1; i <= e; ++i)
    {
        int x = read(), y = read(), z = read();
        add(x, y, z), add(y, x, z);
    }
    d = read();
    for (rint i = 1; i <= d; ++i)
    {
        int p = read(), a = read(), b = read();
        
        for (rint i = a; i <= b; ++i) stop[p][i] = 1;//stop[i][j]表示第i点j天不开 
    } 
    for (rint i = 1; i <= n; ++i)
      for (rint j = i; j <= n; ++j)
        cost[i][j] = spfa(i, j);
    memset(dp, 0x3f, sizeof(dp)); dp[0] = 0;
    for (rint i = 1; i <= n; ++i)
      for (rint j = 1; j <= i; ++j)
        dp[i] = min(dp[i], dp[j - 1] + K + cost[j][i] * (i - j + 1));
    write(dp[n] - K);//最后-k因为j=1时没变,dp却+了k 
    return 0;
} 
View Code
原文地址:https://www.cnblogs.com/mxrmxr/p/11569832.html