1. 程式人生 > >[ZJOI2006]物流運輸trans

[ZJOI2006]物流運輸trans

背包 最好 cstring 每次 題目 struct 路線 代碼 sam

Description

物流公司要把一批貨物從碼頭A運到碼頭B。由於貨物量比較大,需要n天才能運完。貨物運輸過程中一般要轉停好幾個碼頭。物流公司通常會設計一條固定的運輸路線,以便對整個運輸過程實施嚴格的管理和跟蹤。由於各種因素的存在,有的時候某個碼頭會無法裝卸貨物。這時候就必須修改運輸路線,讓貨物能夠按時到達目的地。但是修改路線是一件十分麻煩的事情,會帶來額外的成本。因此物流公司希望能夠訂一個n天的運輸計劃,使得總成本盡可能地小。

Input

第一行是四個整數n(1<=n<=100)、m(1<=m<=20)、K和e。n表示貨物運輸所需天數,m表示碼頭總數,K表示每次修改運輸路線所需成本。
接下來e行每行是一條航線描述,包括了三個整數,依次表示航線連接的兩個碼頭編號以及航線長度(>0)。其中碼頭A編號為1,碼頭B編號為m。單位長度的運輸費用為1。航線是雙向的。
再接下來一行是一個整數d,後面的d行每行是三個整數P( 1 < P < m)、a、b(1 < = a < = b < = n)。表示編號為P的碼頭從第a天到第b天無法裝卸貨物(含頭尾)。同一個碼頭有可能在多個時間段內不可用。但任何時間都存在至少一條從碼頭A到碼頭B的運輸路線。

Output

包括了一個整數表示最小的總成本。總成本 = n天運輸路線長度之和 + K * 改變運輸路線的次數。

Sample Input

5 5 10 8
1 2 1
1 3 3
1 4 2
2 3 2
2 4 4
3 4 1
3 5 2
4 5 2
4
2 2 3
3 1 1
3 3 3
4 4 5

Sample Output

32

題解: 這個題目正解是spfa,DP,這個題解不難想出是這個,DP也不難理解,就是狀態轉移有點難想,首先我們可以把任意i~j中可以走那些點處理出來,進而處理出任意i~j天如果都用一種走法的最小花費(不考慮k值)求出來,用spfa很好求。最好就是DP了,設dp[i]表示前i天的最小花費,轉移很巧妙dp[i]=max(dp[j]+cost[j+1][i]*(i-j)+k)。註意dp[0]=-k;很好理解,就是一個類似完全背包的東西,dp[0]=-k,就把方案路徑相等的情況考慮進來了。 代碼:
#include<iostream>
#include
<stdio.h> #include<stdlib.h> #include<algorithm> #include<cstring> #include<queue> const int MAXN=1000; using namespace std; int n,m,k,e,d,num=0; struct edge{ int first; int next; int quan; int to; }a[MAXN*2]; int dis[MAXN],have[MAXN],can[120][120][120]; int dp[MAXN],cost[120
][120],inf; queue<int> q; void addedge(int from,int to,int quan){ a[++num].to=to; a[num].quan=quan; a[num].next=a[from].first; a[from].first=num; } void cl(){ memset(dis,37,sizeof(dis)); memset(have,0,sizeof(have)); memset(dp,37,sizeof(dp)); memset(can,1,sizeof(can)); memset(cost,37,sizeof(cost)); inf=dis[0]; } void spfa(int day1,int day2){ while(!q.empty())q.pop(); for(int i=1;i<=m;i++) have[i]=0; for(int i=1;i<=m;i++) dis[i]=dp[0]; q.push(1); dis[1]=0,have[1]=1; while(!q.empty()){ int now=q.front(); q.pop(); have[now]=0; for(int i=a[now].first;i;i=a[i].next){ int to=a[i].to; int quan=a[i].quan; if(!can[to][day1][day2]) continue; if(dis[to]>dis[now]+quan){ dis[to]=dis[now]+quan; if(!have[to]){ have[to]=1; q.push(to); } } } } cost[day1][day2]=dis[m]; } int main(){ cl(); 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); addedge(x,y,z); addedge(y,x,z); } scanf("%d",&d); for(int i=1;i<=d;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); if(y>z) swap(y,z); for(int i=1;i<=z;i++) for(int j=y;j<=n;j++) if(i<=j) can[x][i][j]=0; } for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) spfa(i,j); dp[0]=-k; for(int i=1;i<=n;i++){ for(int j=0;j<i;j++){ if(cost[j+1][i]==inf||dp[j]==inf) continue; dp[i]=min(dp[j]+cost[j+1][i]*(i-j)+k,dp[i]); } } printf("%d",dp[n]); }

[ZJOI2006]物流運輸trans