สมมติว่าเรามีรายการตัวเลขที่เรียกว่า nums และอีกค่าหนึ่งคือ k เราสามารถแบ่งรายการออกเป็น k รายการย่อยที่ไม่ว่างเปล่า เราต้องหาผลรวมต่ำสุดของ k รายการย่อย
ดังนั้น หากอินพุตมีค่าเท่ากับ nums =[2, 4, 3, 5, 12] k =2 ผลลัพธ์จะเป็น 14 เนื่องจากเราสามารถแบ่งรายการได้ดังนี้ [2, 4, 3, 5] และ [ 12].
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
-
กำหนดฟังก์ชัน ok() ซึ่งจะใช้อาร์เรย์ v, k, x,
-
cnt :=0, ผลรวม :=0
-
สำหรับแต่ละองค์ประกอบ i ใน v -
-
ถ้า sum + i> x แล้ว −
-
ผลรวม :=ผม
-
(เพิ่มขึ้นอีก 1)
-
-
มิฉะนั้น
-
sum :=sum + i
-
-
-
คืนค่า จริง เมื่อ cnt <=k ไม่เช่นนั้น เท็จ
-
จากวิธีหลัก ให้ทำดังต่อไปนี้ −
-
ต่ำ :=0, ถอยหลัง :=0, สูง :=0
-
สำหรับแต่ละองค์ประกอบ i เป็น nums
-
สูง :=สูง + ผม
-
ret :=ret + ผม
-
ต่ำ :=สูงสุดของค่าต่ำสุดและ i
-
-
ในขณะที่ต่ำ <=สูง ทำ -
-
กลาง :=ต่ำ + (สูง - ต่ำ) / 2
-
ถ้า ok(nums, k - 1, mid) เป็นจริง −
-
ret :=กลาง
-
สูง :=กลาง - 1
-
-
มิฉะนั้น
-
ต่ำ :=กลาง + 1
-
-
-
รีเทิร์น
ตัวอย่าง
ให้เราดูการใช้งานต่อไปนี้เพื่อความเข้าใจที่ดีขึ้น -
#include <bits/stdc++.h>
using namespace std;
bool ok(vector <int>& v, int k, int x){
int cnt = 0;
int sum = 0;
for(int i : v){
if(sum + i > x){
sum = i;
cnt++;
}
else{
sum += i;
}
}
return cnt <= k;
}
int solve(vector<int>& nums, int k) {
int low = 0;
int ret = 0;
int high = 0;
for(int i : nums){
high += i;
ret += i;
low = max(low, i);
}
while(low <= high){
int mid = low + ( high - low) / 2;
if(ok(nums, k - 1, mid)){
ret = mid;
high = mid - 1;
}
else{
low = mid + 1;
}
}
return ret;
}
int main(){
vector<int> v = {2, 4, 3, 5, 12};
int k = 2;
cout << solve(v, k);
} อินพุต
{2, 4, 3, 5, 12}, 2 ผลลัพธ์
14