UVA - 714 Copying Books 最大值尽量小

题目大意:给出一系列的数字,按升序排列了,要求将这些数字分成N份,要求每份的最大值值达到最小,问如何划分

解题思路:用二分法求出符合的最小值,刚开始的值在最大值和总和之间,不断细分,知道找到最符合的,因为要前面的尽量小,所以从后面开始枚举

#include<cstdio>
#include<cstring>
long long k,n,num[505],left,right,mid;
int ans[505],a[505],b[505];
bool judge(long long sum) {

	long long pos = 0, cur = 0;
	memset(a,0,sizeof(a));

	for(int i = k; i >= 1; i--)
		if(pos + num[i] < sum && i >= n - cur)
			pos = pos + num[i];
		else {
			pos = num[i];
			a[i] = 1;
			cur++;	
		}

	if(cur + 1 == n) {
		for(int  i = 1; i <= k; i++)
			ans[i] = a[i];
		return true;	
	}

	return false;
}

int main() {

	int test;
	scanf("%d",&test);
	while(test--) {

		memset(ans,0,sizeof(ans));
		scanf("%lld%lld",&k,&n);
		left = right = 0;
		for(int i = 1; i <= k; i++) {

			scanf("%lld", &num[i]);
			right = right + num[i];
			if(left < num[i])
				left = num[i];	
		}

		while(left <= right) {
			mid = (left + right) / 2;
			if(judge(mid)) 
				right = mid - 1;
			else
				left = mid + 1;
		}	

		for(int i = 1; i <= k - 1; i++) 
			if(ans[i])
				printf("%lld / ", num[i]);
			else
				printf("%lld ",num[i]);	
		printf("%lld\n",num[k]);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值