這篇講解部分已經整合進入 。**留在這裡。n個任務排成乙個序列在一台機器上等待完成(順序不得改變),這n個任務被分成若干批,每批包含相鄰的若干任務。從時刻0開始,這些任務被分批加工,第i個任務單獨完成所需的時間是ti。在每批任務開始前,機器需要啟動時間s,而完成這批任務所需的時間是各個任務需要時間的總和(同一批任務將在同一時刻完成)。每個任務的費用是它的完成時刻乘以乙個費用係數fi。請確定乙個分組方案,使得總費用最小。
例如:s=1;t=;f=。如果分組方案是、、,則完成時間分別為,費用c=,總費用就是153。
5
1 1 3
3 2
4 3
2 3
1 4
153
很顯然,由於順序不能改變,所以可以使用dp來求解。狀態是關鍵!下面給出兩個不同的方法,由於狀態不同,複雜度相去甚遠。
雖然時間就是金錢,但是這裡我們會把f值看作金錢,而時間看成金錢的單位。
費用s = t * f,顯然s = f+f+f...(t個f)。
所以時間t每增加k,即t
' = t+k,
那麼s' - s = kf。
我們便說:金錢又被收了k次。
這是一種最顯然的方法,即記錄下當前時間,在決策時直接使用sigma(time) * f
獲取當前費用。不妨用dp[i][t]
表示從t秒開始,完成任務i到n所需最小費用。不難得出dp方程:
dp[i][t] = min
k = i..n
邊界:dp[n+1][..] = 0
目標:dp[1][0]
順著剛才的思路,我們考慮每當乙個決策可能在未來產生消費時,就立刻預先支付這個價值。建議各位先深刻理解劉汝佳/黃亮黑書p151的最優二分檢索樹是如何推算出dp方程的。
分析問題: 每個任務的費用是它的完成時刻乘以乙個費用係數fi。不妨看成費用係數fi進行了連續加法,當前決策之前的每乙個決策每使時間過去了1,就要在當前費用中加上乙個fi;反過來,當前的決策每使時間增加k分鐘,或者如開頭所說收了k次錢,就會使它以及其後的每乙個任務的費用加上fi。正是這種化乘法為加法的思路,削去了冗餘的時間一維。由此得出dp方程:
dp[i]表示第i個到第n個任務所需的費用
dp[i] = min
其中 i ≤ j ≤ n
邊界是 dp[n+1]=0
目標是 dp[1]
深刻理解這個方程,會受益匪淺。
方程中可以看出,i是遞減的,無腦給出c++**
#include
#include
using
namespace
std;
#define ll int64_t
ll dp[5005];
ll sumt[5005],sumf[5005];
int n,s;
int main()
for (int i=n; i>=1; i--)
}cout
<< dp[1] << endl;
return
0;}
Tyvj1098 任務安排
恕我懶 分析 本蒟蒻只想到了辣雞做法 f i,j 表示前j個任務分了i組,最少費用,f i,j min 發現這是o n 3 的,水不過去.於是腦洞大開想寫乙個二維的斜率優化.不知道為什麼一直wa了乙個點.於是去尋找正解,發現只需要開1維陣列就夠了,驚呆我了.用f i 表示從第i個任務開始做的最小費用...
TYVJ 1098 任務安排
n個任務排成乙個序列在一台機器上等待完成 順序不得改變 這n個任務被分成若干批,每批包含相鄰的若干任務。從時刻0開始,這些任務被分批加工,第i個任務單獨完成所需的時間是ti。在每批任務開始前,機器需要啟動時間s,而完成這批任務所需的時間是各個任務需要時間的總和 同一批任務將在同一時刻完成 每個任務的...
Tyoj1098 任務安排
n個任務排成乙個序列在一台機器上等待完成 順序不得改變 這n個任務被分成若干批,每批包含相鄰的若干任務。從時刻0開始,這些任務被分批加工,第i個任務單獨完成所需的時間是ti。在每批任務開始前,機器需要啟動時間s,而完成這批任務所需的時間是各個任務需要時間的總和 同一批任務將在同一時刻完成 每個任務的...