P1772 [ZJOI2006]物流运输 dp+最短路
题意:给出一个图,给出这个图要走多少次(一天一次)
给出每一个点在哪一次(天)不能用
给出每一次改变路径的花费
让我们求走n次(天)的最小花费
思路:dp+最短路
状态转移方程为:dp[i]=mn(dp[i],dp[j]+k+tmp2[j+1][i]*(i-j));
于是,我们需要求出每一个tmp2【i】【j】,表示的意思是在从i到j的天数内走这一条路径的花费
那么要想求出tmp2,我们就需要枚举天数段,求出每一个区间内的值,
想要求出每一个区间内的值,就需要得出在这个区间内不能够用的点
1 for(int i=1;i<=n;i++) 2 for(int j=i;j<=n;j++){ 3 memset(visnot,0,sizeof(vis)); 4 for(int y=i;y<=j;y++) 5 for(int u=1;u<=m;u++){ 6 if(tmp1[u][y]) visnot[u]=1; 7 } 8 SPFA(); 9 tmp2[i][j]=dis[m]; 10 }
然后最后再跑一遍dp过程即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int inf=0x3f3f3f3f; 5 const int maxn=400; 6 int tmp1[maxn][maxn]; 7 int tmp2[maxn][maxn]; 8 int visnot[30]; 9 int vis[30];int dis[30]; 10 ll dp[30]; 11 struct node 12 { 13 int v,w,nxt; 14 }G[maxn]; int head[maxn]; int num; 15 void add(int u,int v,int w) 16 { 17 G[++num].v=v;G[num].w=w;G[num].nxt=head[u];head[u]=num; 18 } 19 ll mn(ll t1,ll t2) 20 { 21 if(t1<=t2) return t1; 22 else return t2; 23 } 24 void SPFA() 25 { 26 queue<int>q; 27 memset(vis,0,sizeof(vis)); 28 memset(dis,inf,sizeof(dis)); 29 q.push(1); 30 vis[1]=1; dis[1]=0; 31 while(!q.empty()){ 32 int u=q.front(); 33 q.pop(); 34 vis[u]=0; 35 for(int i=head[u];i;i=G[i].nxt){ 36 int v=G[i].v,w=G[i].w; 37 if(visnot[v]) continue; 38 if(dis[v]>dis[u]+w){ 39 dis[v]=dis[u]+w; 40 if(!vis[v]){ 41 vis[v]=1; 42 q.push(v); 43 } 44 } 45 } 46 } 47 } 48 int main() 49 { 50 int n,m,k,e; 51 scanf("%d%d%d%d",&n,&m,&k,&e); 52 for(int i=1;i<=e;i++){ 53 int u,v,w; 54 scanf("%d%d%d",&u,&v,&w); 55 add(u,v,w); 56 add(v,u,w); 57 } 58 int T; 59 scanf("%d",&T); 60 while(T--){ 61 int cnt,u,v; 62 scanf("%d%d%d",&cnt,&u,&v); 63 for(int i=u;i<=v;i++){ 64 tmp1[cnt][i]=1; 65 } 66 } 67 for(int i=1;i<=n;i++) 68 for(int j=i;j<=n;j++){ 69 memset(visnot,0,sizeof(vis)); 70 for(int y=i;y<=j;y++) 71 for(int u=1;u<=m;u++){ 72 if(tmp1[u][y]) visnot[u]=1; 73 } 74 SPFA(); 75 tmp2[i][j]=dis[m]; 76 } 77 for(int i=1;i<=n;i++) 78 dp[i]=1e16; 79 for(int i=1;i<=n;i++){ 80 dp[i]=1ll*tmp2[1][i]*i; 81 for(int j=1;j<i;j++){ 82 dp[i]=mn(dp[i],dp[j]+1ll*k+1ll*tmp2[j+1][i]*(i-j)); 83 } 84 } 85 printf("%lld\n",dp[n]); 86 return 0; 87 }