清潔工:假設有m個房間,清潔每個房間耗時用乙個陣列表示,10、20、30、40、50、60、70、80、90,安排n個清潔工,將連續的房間分成n份,每部分耗時求和,其最大值為此種分法的總耗時。求最快的耗時是多少。例如3個清潔工的話,10 20 30 40 50 | 60 70 | 80 90,此時是最快的,耗時為170。解析:題目:給定乙個陣列,和乙個值k,陣列分成k段。要求這k段子段和最大值最小。求出這個值。
使用dp[n][k]表示前n個房間,k個清潔工的最優解dp
[n][
k]=m
in⎧⎩
⎨⎪⎪⎪
⎪⎪⎪m
ax(d
p[0]
[k−1
],∑n
i=0a
[i])
max(
dp[1
][k−
1],∑
ni=1
a[i]
)...
max(
dp[n
][k−
1],∑
ni=n
a[i]
) 此題可以想象成把資料按順序裝入桶中,m即是給定的桶數,問桶的容量至少應該為多少才能恰好把這些數裝入k個桶中(按順序裝的)。
首先我們可以知道,桶的容量最少不會小於陣列中的最大值,即桶容量的最小值(小於的話,這個數沒法裝進任何桶中),假設只需要乙個桶,那麼其容量應該是陣列所有元素的和,即桶容量的最大值;其次,桶數量越多,需要的桶的容量就可以越少,即隨著桶容量的增加,需要的桶的數量非遞增的(二分查詢就是利用這點);我們要求的就是在給定的桶數量m的時候,找最小的桶容量就可以把所有的數依次裝入k個桶中。在二分查詢的過程中,對於當前的桶容量,我們可以計算出需要的最少桶數requiredpainters,如果需要的桶數量大於給定的桶數量k,說明桶容量太小了,只需在後面找對應的最小容量使需要的桶數恰好等於k;如果計算需要的桶數量小於等於k,說明桶容量可能大了(也可能正好是要找的最小桶容量),不管怎樣,該桶容量之後的桶容量肯定不用考慮了(肯定大於最小桶容量),這樣再次縮小查詢的範圍,繼續迴圈直到終止,終止時,當前的桶容量既是最小的桶容量。
#include
#include
#include
#include
#include
#include
#include
using
namespace::std;
#define debug_
bool isok(vector
& vec,int k, long
long tmp_max)
}if (count>k)
return
false;
else
return
true;
}int func(vector
& vec,int k)
else
mid = left + ((right - left) >> 1);
}return right;
}int main()
;int a = ;
vec.insert(vec.begin(),a,a+11);
k = 3;
#else
#endif
cout
0;}
陣列(list)分組 分段
對乙個list進行分組,要求控制每組中的元素個數 1.使用切片分組 lst 1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1 lst可為空,最後返回值也為空 num 3 定義每組包含的元素個數 for i in range 0,len lst num print lst i i n...
陣列(list)分組 分段
對乙個list進行分組,要求控制每組中的元素個數 1.使用切片分組 lst 1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1 lst可為空,最後返回值也為空 num 3 定義每組包含的元素個數 for i in range 0,len lst num print lst i i n...
演算法 陣列分段和最大值最小問題
題目 給定乙個陣列,和乙個值k,陣列分成k段。要求這k段子段和最大值最小。求出這個值。n n 1 m n,k min j 1 i j n表示陣列長度,k表示陣列分成幾段。初始化條件 m 1,k a0 n 1 m n,1 ai i 0遞迴演算法擁有指數時間的複雜度,並且會重複計算一些m值。這類的演算法...