https://leetcode.com/contest/biweekly-contest-11/problems/divide-chocolate/算法
這道題的題目意思就是,一個巧克力有n格,每一個格子有不一樣的甜度,將巧克力切k次,選擇甜度最低的那塊,問怎麼切可以使得甜度最低的那塊巧克力甜度最大。ide
比賽的時候第一反應這裏有一個很明顯的遞推關係:從切k-1塊到切k塊,從k-1加上連續的1~n格就能獲得下一個狀態,因而很快就獲得了一個超時的n3 dp:spa
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值,並判斷是否知足條件(最多能切成幾份)。也就是說咱們能夠使用二分猜答案,假設答案爲某個值,若是題目存在這麼一個臨界條件,咱們就能經過二分找到這個臨界值。code
最終的算法複雜度爲:O(nlogn)blog
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/ip
題意是輪船一天運一次貨,要求最少D天把貨物運到(條件存在限制),求輪船的最小容量(求邊界結果)。ci
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; } };