最短路+dp
a[i][j]表示符合第i天到第j天情况的一条最短路
dp方程 dp[i]=min(dp[i],dp[j]+k+(i-j)*a[j+1][i]);
注意要开long long...
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
const int oo=99999999;
struct node
{
int t,x;
};
vector<node> mp[21];
int n,m,k,e,a[110][110];
bool f[110][110];
int djs(int s,int t)
{
bool vis[110],flag[110];
int dist[110];
for (int i=1;i<=m;i++)
dist[i]=oo;
dist[1]=0;
memset(vis,true,sizeof(vis));
memset(flag,true,sizeof(flag));
for (int i=1;i<=m;i++)
for (int j=s;j<=t;j++)
if (!f[j][i]) flag[i]=false;
for (int i=1;i<=m-1;i++)
{
int min=oo,u;
for (int j=1;j<=m;j++)
if (flag[j]&&vis[j]&&dist[j]<min) u=j,min=dist[j];
vis[u]=false;
for (int j=0;j<(int)mp[u].size();j++)
if (flag[mp[u][j].t])
{
if (dist[u]+mp[u][j].x<dist[mp[u][j].t])
dist[mp[u][j].t]=dist[u]+mp[u][j].x;
}
}
return dist[m];
}
int main()
{
scanf("%d%d%d%d",&n,&m,&k,&e);
for (int i=1;i<=e;i++)
{
int s,t,x;
scanf("%d%d%d",&s,&t,&x);
node tt;
tt.t=t;
tt.x=x;
mp[s].push_back(tt);
tt.t=s;
tt.x=x;
mp[t].push_back(tt);
}
memset(f,true,sizeof(f));
int d;
scanf("%d",&d);
for (int i=1;i<=d;i++)
{
int ta,tb,tc;
scanf("%d%d%d",&ta,&tb,&tc);
for (int j=tb;j<=tc;j++)
f[j][ta]=false;
}
for (int i=1;i<=n;i++)
for (int j=i;j<=n;j++)
a[i][j]=djs(i,j);
long long dp[110];
dp[1]=a[1][1];
for (int i=2;i<=n;i++)
{
dp[i]=a[1][i]*(long long)i;
for (int j=1;j<i;j++)
dp[i]=min(dp[i],dp[j]+k+(i-j)*(long long)a[j+1][i]);
}
cout<<dp[n]<<endl;
return 0;
}