ZJOI2006 物流運輸
阿新 • • 發佈:2018-08-18
多少 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--) #defineenter 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 物流運輸