POJ 3273 月度最大花费

#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小节中对改进后的二分搜索的正确性通过循环不变式理论做了详尽的论述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值