这是一道DP+最短路径的好题。
首先预处理每天每个点的最短路径。
用SPFA进行处理。即cost[i][j]为第i天到底j天的1到M点的最小花费。
就可以水水的DP。
设f[i]为第i天的最优方案,f[i]=min(f[i],f[j]+cost[j+1][i]*(i-j)+K);
即从第j天之后开始改变航线。
code:
/************************************************************** Problem: 1003 User: yekehe Language: C++ Result: Accepted Time:32 ms Memory:1536 kb ****************************************************************/ #include <bits/stdc++.h> using namespace std; int N,M,K,e,mp[21][21],wi[21][101],tag[21]; int cost[101][101],f[101],dist[21],l[50001],h,t,flag[21]; int spfa(){ h=t=0; l[++t]=1;dist[1]=0; while(h<t){ int front=l[++h];flag[front]=0; for(int i=1;i<=M;i++){ if(mp[front][i]&&dist[front]+mp[front][i]<dist[i]){ dist[i]=dist[front]+mp[front][i]; if(!flag[i]&&!tag[i])l[++t]=i,flag[i]=1; } } } return dist[M]; } int main(){ scanf("%d%d%d%d",&N,&M,&K,&e); for(int i=1;i<=e;i++){ int x,y,c; scanf("%d%d%d",&x,&y,&c); mp[x][y]=mp[y][x]=c; } int R;scanf("%d",&R); for(int i=1;i<=R;i++){ int p,x,y;scanf("%d%d%d",&p,&x,&y); for(int j=x;j<=y;j++)wi[p][j]=1; } for(int i=1;i<=N;i++){memset(tag,0,sizeof(tag)); for(int j=i;j<=N;j++){ for(int k=1;k<=M;k++)tag[k]|=wi[k][j]; memset(dist,63,sizeof(dist)); cost[i][j]=spfa(); } } for(int i=1;i<=N;i++){f[i]=1e8; for(int j=0;j<i;j++){ if(cost[j+1][i]!=1061109567)f[i]=min(f[i],f[j]+cost[j+1][i]*(i-j)+K); } } printf("%d",f[N]-K); }