題目大意:把這個數組分爲d份,每份至少爲1個元素,每份的最大值爲這份的值,求所有份的和的最小值。
本題用工作計劃的形式表達了一下,份數用天數表示,每份的值用工作量表示。
題目思路:求最小值問題,用動態規劃dp。
詳細思路:按天數和工作量兩個變量,構造遞歸式dp[天數][完成的任務數量] = 工作量的最小值:
1、按照工作量:即1天完成k個任務,爲dp[1][k]=max{dp[1][k-1], job[k]},即每份的最大值代表這份的值,用第1天來表示,同時完成了dp初始化;
2、按照天數 dp[d][k] = min{dp[d][k], dp[d-1][l] + maxl}, 即第d天所有份和的最小值,爲{d-1天完成了l項任務的最小值 + k-l區間中任務的最大值(maxl)} 集合中的最小值。
3、需要注意每天至少有1個任務,那麼需要保障第d天前面至少有d個任務已完成,那麼遞歸式2中,k-l最小值爲d,而不能爲0。
詳細代碼如下:
class Solution {
public:
int minDifficulty(vector<int>& j, int d) {
js=j.size();
if(js < d)
{
return -1;
}
/////////////
dp[1][1]=j[0];
for(int i=0;i<js;i++)//遞歸式1,求工作量的最大值,初始化
{
dp[1][i+1]=max(dp[1][i],j[i]);
}
for(int i=1;i<=d;i++)//遞歸式2,求天數的最小值
{
for(int k=i;k<=js;k++)//k從i開始,對應於條件:每天至少需要完成一項任務
{
int maxk=INT_MIN;
for(int l=k-1;l>=i;l--)//參照遞歸式1,求k-1到i的區間最大值
{
maxk=max(maxk,j[l]);
if(dp[i+1][k] == 0)
dp[i+1][k]=dp[i][l]+maxk;
else
dp[i+1][k] =min(dp[i+1][k],dp[i][l]+maxk);
}
}
}
return dp[d][js];
}
int js;
int dp[12][301];
};
在dp中,爲了我自己方便理解,用dp[1][1]表示第1天完成1項任務,而不是從0開始。