这道题数据范围很小。
用f[i]表示前i天的最小代价,那么f[i]=min{f[j]+cost(j+1,i)+k}
cost表示从j+1天到第i天找一条 唯一的 最短路径 的长度
#include<cstdio>
#include<cstdlib>
#include<cstring>
int n,m,k,e;
int first[25];
struct mod{int x,y,z,next;};
mod q[1005];
bool can[25][105];
int t[105];
bool v[105];
int f[105];
int s[105];
int len=0;
void ins(int x,int y,int z)
{
len++;
q[len].x=x;
q[len].y=y;
q[len].z=z;
q[len].next=first[x];
first[x]=len;
}
int mymin(int u1,int u2)
{
if (u1<u2)return u1;
return u2;
}
int cost(int stday,int edday)
{
int st=1,ed=2;
memset(v,false,sizeof(v));
v[1]=true;
for (int i=2;i<=m;i++)
s[i]=999999999;
s[1]=0;
t[1]=1;
while(st!=ed)
{
int x=t[st];
for (int i=first[x];i!=0;i=q[i].next)
{
int y=q[i].y;
bool tf=true;
for (int j=stday;j<=edday;j++)
{
if (can[y][j]==false)
{tf=false;break;}
}
if (tf==false)continue;
if (s[x]+q[i].z<s[y])
{
s[y]=s[x]+q[i].z;
if (v[y]==false)
{
v[y]=true;
t[ed]=y;
ed++;
if (ed>m)ed=1;
}
}
}
v[x]=false;
st++;
if (st>m)st=1;
}
if (s[m]>999999998)
return -1;
else
return (edday-stday+1)*s[m];
}
int main()
{
scanf("%d%d%d%d",&n,&m,&k,&e);
for (int i=1;i<=e;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
ins(x,y,z);
ins(y,x,z);
}
memset(can,true,sizeof(can));
int D;
scanf("%d",&D);
for (int i=1;i<=D;i++)
{
int p,a,b;
scanf("%d%d%d",&p,&a,&b);
for (int j=a;j<=b;j++)
can[p][j]=false;
}
for (int i=1;i<=n;i++)
{
int soy=cost(1,i);
if (soy!=-1)
f[i]=soy;
else
f[i]=999999999;
for (int j=1;j<i;j++)
{
int soy=cost(j+1,i);
if (soy==-1)continue;
f[i]=mymin(f[i],f[j]+soy+k);
}
}
printf("%d\n",f[n]);
}