最大值最小化 二分查找

把一个包含n个正整数的序列划分成m个连续的子序列(每个正整数恰好属于一个序列)。设第i个序列的各数之和为S(i),你的任务是让所有S(i)的最大值尽量小。
     例如序列1 2 3 2 5 4 划分成3个序列的最优方案为1 2 3| 2 5| 4,其中S(1)、S(2),S(3)分别为6、7、4最大值为7;
     如果划分成1 2 |3 2| 5 4, 则最大值为9,不如刚才好。n <= 10^6 ,所有数之和不超过10^9。
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <tgmath.h>
using namespace std;
int n,k;
int s[20],s1[20];
bool calcu(int x)
{
	int num = 0;
	int sum = 0; 
	for(int i = 0;i<n;i++)
	{
		if(s[i]>x)
		{
			return false;
		}
		if(sum+s[i]>x)
		{
			s1[i-1] = 1;
			sum = s[i];
			num++;
			if(num > k-1)
				return false;
		}
		else 
		{
			sum+=s[i];
		}
	}
	return true;
}	
int main()
{
	int num;
	while(scanf("%d%d",&n,&k)!=EOF)
	{
		int y = 0;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&s[i]);
			y+=s[i];
		}
		int x = 0;
		while(y>x)
		{
			memset(s1,0,sizeof(s1));
			num = x+(y-x)/2;
			if(calcu(num))
				y = num;
			else
				x = num+1;
		}
		for(int i = 0;i< n;i++)
		{
			if(s1[i] == 1)
				printf("%d | ",s[i]);
			else
				printf("%d ",s[i]);
		}
		printf("\n");
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值