洛谷1594 護衛隊 區間dp 題解

2021-10-05 12:17:53 字數 1623 閱讀 8841

出自洛谷題庫

【問題描述】不是具體題目

大概就是有n個車要過河,只有乙個橋(理論上只能單向通行,其實不用管對面),橋有最大承重,每次你可以把其中的任意一段(length<=n)輛車組成車隊,同時通過。要求總時間的最小值。

【題目分析】

一開始我在摸索的時候,感覺這道題目有種多個01揹包放在一起的感覺,因此,我開始腦補時間複雜度。。。要列舉有幾個01揹包,要列舉在**劃分揹包,然後還要多個01揹包的o(n*n)的累加。。。

然後。。。正解

首先說,這是一道區間dp,這麼說的原因是車輛的順序給定(不能超車),所以我們只能列舉區間,因此,狀態定義為二維,f[l][r],即區間左端,右端。

然後,狀態轉移方程就是在討論區間的劃分,取最小值。

初始化就是把f[i][i],第i輛車的通過時間直接求出來。

最後。。。注釋很詳細,建議複製到編譯器裡檢視。

【**+注釋】->70分

#include

#include

#include

//不用加

#include

#include

//不用加

#include

#include

using

namespace std;

const

int maxn=

1000

;//固定常量定義陣列上限 (水一下**行數)

double f[maxn+5]

[maxn+5]

;//dp陣列

double w[maxn+5]

[maxn+5]

,t[maxn+5]

[maxn+5]

;//存下任意區間的重量和以及通過時間( 預處理 );

struct group a[maxn+5]

;int

main()

for(

int i=

1;i<=n;i++)}

for(

int len=

2;len<=n;len++)}

//值得注意的是,區間dp不能直接列舉左右端點,因為區間dp本質是從小區間推廣到大區間,只能先從小長度來 (敲黑板)

}printf

("%.1lf\n"

,f[1

][n]*60

);return0;

}

【優化方向】

可以考慮如下方向:

減少預處理的複雜度;

可以通過逆序迴圈來減少乙個dp陣列的維度;(如下)

簡化決策;

【優化**】->滿分

這段**是看過網上的文章後自己理解所寫,無意抄襲

double ans[maxn+5]

;//前i輛車的通過時間最小值

for(

int i=

1;i<=n;i++

) ans[i]

=1e18

;for

(int i=

1;i<=n;i++)}

}printf

("%.1lf\n"

,ans[n]*60

);

全文——終

Luogu P1594護衛隊(字首和 DP)

tm搞了半天的二維dp方程還是錯的。設f i 表示前i輛車順利通過的最小時間。則對於每乙個i列舉該組車的起點j,然後從所有的f j min j i 中選乙個最小的。min j i 表示從第j輛車到第i輛車最慢的是個什麼速度。include include include include using ...

洛谷P1220 關路燈 題解 區間DP

本題涉及演算法 區間dp。我們一開始要做一些初始化操作,令 我們設狀態 f l r i 表示 則我們可以得出狀態轉移方程如下 f l r 0 min f l 1 r 0 sum l sum n sum r p l 1 p l f l 1 r 1 sum l sum n sum r p r p l f...

區間dp 洛谷P1040

這個題目是個區間dp 為什麼會在洛谷的dfs裡面,我也不知道啊 dfs啊呸,區間dp,顧名思義,就是在一段區間 l,r 上的dp 我在說什麼亂七八糟的,劃掉劃掉 乍一看這個題目,看似無從下手 可能只有我自己無從下手 其實仔細一分析,題目要,求最大值,我們就直接列舉樹根,然後把左右兒子按照題目要求的操...