https://leetcode.com/contest/biweekly-contest-11/problems/divide-chocolate/
这道题的题目意思就是,一个巧克力有n格,每个格子有不同的甜度,将巧克力切k次,选择甜度最低的那块,问怎么切能够使得甜度最低的那块巧克力甜度最大。
比赛的时候第一反应这里有一个很明显的递推关系:从切k-1块到切k块,从k-1加上连续的1~n格就能得到下一个状态,于是很快就得到了一个超时的n3 dp:
class Solution {
public:
int n;
int maximizeSweetness(vector<int>& sweetness, int K) {
n = sweetness.size();
vector<vector<int>> dp(n, vector<int>(K + 5, 0));
for(int i = 0;i < n;i++)
{
if(i == 0) dp[i][0] = sweetness[i];
else dp[i][0] = sweetness[i] + dp[i - 1][0];
}
for(int k = 1;k <= K; k++)
{
for(int i = 0;i < n; i++)
{
int sum = 0;
for(int j = i + 1;j < n;j++)
{
sum += sweetness[j];
dp[j][k] = max(dp[j][k], min(dp[i][k - 1], sum));
}
}
}
return dp[n - 1][K];
}
};
再仔细一看这道题的输入数据量是10^4。这道题还存在着一个临界点的问题,它符合了满足某一个临界点(分成k+1份,每份至少有x个),我们就可以假定这个x值,并判断是否满足条件(最多能切成几份)。也就是说我们可以使用二分猜答案,假设答案为某个值,如果题目存在这么一个临界条件,我们就能通过二分找到这个临界值。
最终的算法复杂度为:O(nlogn)
class Solution
{
public:
int getK(vector<int>& sweetness, int min)
{
int sum = 0;
int k = 0;
for(int i = 0;i < sweetness.size();i++)
{
sum += sweetness[i];
if(sum >= min)
{
k++;
sum = 0;
}
}
return k;
}
int maximizeSweetness(vector<int>& sweetness, int K)
{
int low = 0;
int high = 1 << 30;
while(low < high)
{
if(high - low == 1)
{
if(getK(sweetness, high) >= K + 1) return high;
else return low;
}
int mid = (high - low) / 2 + low;
if(getK(sweetness, mid) >= K + 1)
{
low = mid;
}
else
{
high = mid;
}
}
return low;
}
};
一道类似的题:https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/
题意是轮船一天运一次货,要求最少D天把货物运到(条件存在限制),求轮船的最小容量(求边界结果)。
class Solution {
public:
int getDay(vector<int>& weights, int capacity)
{
int sum = 0;
int day = 0;
for(int i = 0;i < weights.size(); i++)
{
sum += weights[i];
if(sum > capacity)
{
day++;
sum = weights[i];
}
}
if(sum != 0) day++;
return day;
}
int shipWithinDays(vector<int>& weights, int D) {
int high = accumulate(weights.begin(), weights.end(), 0);
int low = *max_element(weights.begin(), weights.end());
while(low < high)
{
if(low == high - 1)
{
if(getDay(weights, low) <= D) return low;
else return high;
}
int mid = (high - low) / 2 + low;
if(getDay(weights, mid) <= D)
{
high = mid;
}
else
{
low = mid;
}
}
return low;
}
};