Code:

定义状态 $dp[i]$ 为前 $i$ 天的最小代价。

状态转移为:$dp[i]=min(dp[i],dp[j]+spfa(j+1,i)$ 这里 $spfa(i,j)$ 是指 $(i,j)$ 天中用一种最短路方案的最短路(最小花费)

 

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<deque>
using namespace std;
void setIO(string a){
    freopen((a+".in").c_str(),"r",stdin);
}
const int maxn=30;
const int inf=10000000;
int n,m;
int tag[maxn],head[maxn], to[1000000], nex[1000000],val[1000000],edges;
int a[maxn][200];
long long dp[200];
void add_edge(int u,int v,int c){
    nex[++edges]=head[u], head[u]=edges, to[edges]=v, val[edges]=c;
}
deque<int>Q;
bool inq[100000];
int d[maxn];
int spfa(int l,int r){
    Q.clear();
    for(int i=0;i<maxn;++i) d[i]=inf;
    memset(tag,0,sizeof(tag));
    memset(inq,false,sizeof(inq));
    for(int i=1;i<=m;++i)
        for(int j=l;j<=r;++j)
            if(a[i][j]) tag[i]=1;
    Q.push_back(1);
    d[1]=0,inq[1]=true;

    while(!Q.empty()){
        int u=Q.front();
        Q.pop_front();
        inq[u]=false;
        for(int v=head[u];v;v=nex[v]){
            if(tag[to[v]]) continue;
            if(d[u]+val[v] < d[to[v]]){
                d[to[v]]=d[u]+val[v];
                if(!inq[to[v]]){
                    if(Q.empty()||d[to[v]]<=d[Q.front()]) Q.push_front(to[v]);
                    else Q.push_back(to[v]);
                    inq[to[v]]=true;
                }
            }
        }
    }
    return d[m];
}
void update(long long  &a,long long b){
    if(b<a)a=b;
}
int main(){
    //setIO("input");
    int k,e;
    scanf("%d%d%d%d",&n,&m,&k,&e);
    for(int i=1;i<=e;++i){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add_edge(a,b,c);
        add_edge(b,a,c);
    }

    int cnt;
    scanf("%d",&cnt);//
    for(int i=1;i<=cnt;++i){
        int p,l,r;
        scanf("%d%d%d",&p,&l,&r);
        for(int j=l;j<=r;++j) a[p][j]=1;
    }
    for(int i=1;i<=n;++i)
    {
        dp[i]=spfa(1,i)*i;
        for(int j=1;j<i;++j) 
            update(dp[i],dp[j]+(long long)spfa(j+1,i)*(i-j)+k);
    }
    printf("%lld\n",dp[n]);
    return 0;
}