題目描述
在印刷術發明之前,複製一本書是乙個很困難的工作,工作量很大,而且需要大家的積極配合來抄寫一本書,團隊合作能力很重要。當時都是通過招募抄寫員來進行書本的錄入和複製工作的, 假設現在要抄寫 \(m\) 本書,編號為 \(1,2,3...m\) , 每本書有 \(1 \le x \le 100000\) 頁, 把這些書分配給 \(k\) 個抄寫員,要求分配給某個抄寫員的那些書的編號必須是連續的,每本書只能被乙個抄寫員抄寫。每個抄寫員的速度是相同的,你的任務就是找到乙個最佳的分配方案,使得所有書能夠被抄完的前提下,每個抄寫員所抄寫的頁數最少。
輸入格式
在第一行中,有兩個整數 \(m 和 k, 1<=k,m<=100000\) 。 在第二行中,有 \(m\) 個整數 \(x_i\) 用空格分隔。 所有這些值都為正且小於 \(100000\) 。
輸出格式
輸出一行數字,代表最佳的分配方案中,全部抄寫完畢,抄寫頁數最多的抄寫員所抄寫的頁數。
樣例輸入
9 3
100 200 300 400 500 600 700 800 900
樣例輸出1700
題目分析
這道題目是二分答案。
首先我們可以編寫乙個bool check(int num)
函式來判斷在分配給每個抄寫員 \(num\) 頁書時 \(k\) 個抄寫員是否能夠超寫完 \(m\) 本書。如果可以,\(check(num)\) 返回true
;否則,\(check(num)\) 返回false
。
然後,我們會發現:
那麼在 \(0\) 和 \(\sum_^nx_i\) 之間肯定存在乙個最小的 \(num\) 使得 \(check(num)\) 返回true
。
我們可以發現:
所以如果我們以答案num
為自變數,以答案是否成立(\(check(num)\) 返回的結果)為應變數,我們可以得到乙個應變數隨自變數變化的單調函式曲線。
實現**如下:
#include using namespace std;
const int maxn = 100010;
int m, k; // m表示書有多少本,k表示抄寫員的數量
long long a[maxn]; // a[i]表示第i本書的頁數
// check函式用於判斷分配給沒個抄寫員num頁書的時候能否超寫完
bool check(long long num)
else if (a[i] > num) // 如果a[i]>num,說明任何抄寫員都抄寫不了第i本書
return false;
else
}return true; // 返回true
}int main()
long long l = 0, r = sum, res; // l記錄答案的左邊界,r記錄答案的右邊界,res記錄答案
while (l <= r)
else l = mid + 1; // 進有半部分找解
}cout << res << endl; // 輸出答案
return 0;
}
二分 最小化最大值
注意答案的二分性質,必須要滿足在滿足給定條件的所有情況的時候都滿足要求才能更新ans。include using namespace std typedef long long ll inline ll in while c 0 c 9 res res 10 c 48,c getchar retur...
zzuli 1919 二分 最大值最小化
description 晴天想把乙個包含n個整數的序列a分成連續的若干段,且和最大的一段的值最小,但他有強迫症,分的段數不能超過m段,然後他就不會分了。他想問你這個分出來的和最大的一段的和最小值是多少?input 第一行輸入乙個整數t,代表有t組測試資料。每組資料第一行為兩個整數n,m分別代表序列的...
POJ 3273(二分,最小化最大值)
和這道題一樣了 description 聰哥在暑假參加了打零工的活動,這個活動分為n個工作日,每個工作日的工資為vi。有m個結算工錢的時間,聰哥可以自由安排這些時間,也就是說什麼時候拿錢,老闆說的不算,聰哥才有發言權!因為聰哥是土豪,他是老闆的老闆 聰哥不喜歡身上一次性有太多的錢,於是他想安排一下拿...