#include<iostream>
#include<fstream>
using namespace std;
static const int MAXDAYS = 100000;
static int money[MAXDAYS];
//#define DEBUG
int main()
{
#ifdef DEBUG
fstream cin("G:\\book\\algorithms\\acm\\Debug\\dat.txt");
#endif
int n, m;
int i;
int max, sum;
cin >> n >> m;
sum = 0; max = -1;
for (i = 0; i < n; i++)
{
cin >> money[i];
sum += money[i];
if (money[i] > max)
max = money[i];
}
int low, high, mid;
low = max - 1; high = sum;
while (low + 1 != high) /* */
{
int tmp;
int f;
mid = (low + high) / 2; /* */
for (f = 1, tmp = 0, i = 0; i < n; i++)
{
tmp += money[i];
if (tmp > mid)
{ f++; tmp = money[i];}
}
/* */
if (f > m)
low = mid;
else
high =mid;
}
cout << high << "\n";
return 0;
}
该题是二分查找的典型应用,其理论基础可以参见《编程珠玑》中第9章,9.3小节中对二分搜索的讨论。满足该题中划分的最大花费的范围 [max, sum], 但是满足条件的key 可能有多个,只有最小的那个才是题目所要求的。最小的就是第一次出现的。在《编程珠玑》中第9章,9.3小节中对改进后的二分搜索的正确性通过循环不变式理论做了详尽的论述。