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

ZJOI2006 物流運輸

多少 eof cond i++ truct 復雜度 n) utility target

題目傳送門

看題目描述中,碼頭的個數小的可憐,竟然只有20,一開始想會不會又是網絡流或者狀壓DP啥的。(好像狀壓DP真能做QAQ)

不過讀完題之後,發現這應該是一道求最短路的題,而且還不只是最短路,既然又可以改道又要求最小花費,那麽肯定還有DP.

最短路+DP的結合題。我們可以這麽考慮,反正這題數據範圍賊小,我們不如先預處理出來第i天到第j天全部能跑的一條最短路的長度是多少(如果不存在就是INF),之後呢,我們用dp[i]來表示到第i天的最小花費。那麽就可以得知,dp[i] = min(dp[i],dp[j] + cost[j+1][i] + k);枚舉從1到i-1的j 就可以了。

為什麽可以這麽做呢?我們考慮,如果有一條路,在第n天可以走,而在第n+1天不能走,那麽此時我們就必須要改道。而改道我們直接在DP的時候考慮就好,那我們只要去求每種情況下不改道的話花費就可以。之後在DP枚舉的時候,總會枚舉到所有的改道和不改道的情況的。註意cost如果不是INF,要乘以其能走的天數。

這樣可以保證考慮到所有情況。時間復雜度n^2*m^2,可以過。

看一下代碼。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<set>
#include<utility>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define
enter putchar(‘\n‘) using namespace std; typedef long long ll; typedef pair<int,int> pr; const int INF = 2e9; const int M = 2005; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < 0 || ch > 9) { if(ch == -) op = -1; ch = getchar(); }
while(ch >= 0 && ch <= 9) { ans *= 10; ans += ch - 0; ch = getchar(); } return ans * op; } struct node { int next,to,v; }e[M<<1]; set <pr> q; set <pr> :: iterator it; int ecnt,head[M],n,m,k,ei,d,p,a,b,cost[105][105],dp[105],dis[25],x,y,z; bool pd[30][105],bro[30]; void add(int x,int y,int z) { e[++ecnt].to = y; e[ecnt].v = z; e[ecnt].next = head[x]; head[x] = ecnt; } int dij(int s) { rep(i,1,m) dis[i] = INF; dis[s] = 0,q.insert(make_pair(dis[s],s)); while(!q.empty()) { pr now = *(q.begin()); q.erase(q.begin()); for(int i = head[now.second];i;i = e[i].next) { if(dis[e[i].to] > dis[now.second] + e[i].v && !bro[e[i].to]) { it = q.find(make_pair(dis[e[i].to],e[i].to)); if(it != q.end()) q.erase(it); dis[e[i].to] = dis[now.second] + e[i].v; q.insert(make_pair(dis[e[i].to],e[i].to)); } } } return dis[m]; } int main() { n = read(),m = read(),k = read(),ei = read(); rep(i,1,ei) x = read(),y = read(),z = read(),add(x,y,z),add(y,x,z); d = read(); rep(i,1,d) { p = read(),a = read(),b = read(); rep(j,a,b) pd[p][j] = 1; } rep(i,1,n) { rep(j,i,n) { memset(bro,0,sizeof(bro)); rep(f,1,m) rep(c,i,j) bro[f] |= pd[f][c]; cost[i][j] = dij(1); } } rep(i,1,n) rep(j,i,n) if(cost[i][j] < INF) cost[i][j] *= (j-i+1); rep(i,1,n) dp[i] = cost[1][i]; rep(i,2,n) rep(j,1,i-1) dp[i] = min(dp[i],dp[j] + cost[j+1][i] + k); printf("%d\n",dp[n]); return 0; }

ZJOI2006 物流運輸