1. 程式人生 > >UVA714給出n個數分成m個部分,使和最大的最小

UVA714給出n個數分成m個部分,使和最大的最小

這題,小白書上有講,所以當時也沒多想直接二分,分完之後,發現有問題,他說前面的儘量小,這裡就要貪心,

從後面貪心,只要和值不大於二分的值就一直二分,然後發現還是不對,看了別人的,忽略了一個問題,二分的時候

x的初始值不能是零,因為我寫的判斷二分的函式比較特殊,所以如果判斷的值小於全部的數也能過,所以,這裡x的

初值注意取全部數的最大值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#define LL long long
using namespace std;
const int maxn=1e4+10;
const double eps=1e-6;
int m,k;
int a[510];
int ca[1110];
bool solve(LL t)
{
	LL sum=0;
	int tem=k-1;
	for(int i=0;i<m;i++)
	{
		if(sum+a[i]>t)
		{
			sum=0;
			tem--;
		}
		if(tem<0)
		return 0;
		sum+=a[i];
	}
	return 1;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		cin>>m>>k;
		LL x=0,y=0;
		for(int i=0;i<m;i++)
		{
			scanf("%d",&a[i]);
			x=max(x,(LL)a[i]);
			y+=a[i];
		}
		if(k==1)
		{
			for(int i=0;i<m-1;i++)
			cout<<a[i]<<' ';
			cout<<a[m-1]<<endl;
			continue;
		}
		while(x<y)
		{
			LL tt=x+(y-x)/2;
			if(solve(tt))
			y=tt;
			else
			x=tt+1;
		}
	//	cout<<x<<endl;
		k--;
		int l=0;
		LL tem=a[m-1];
		memset(ca,0,sizeof(ca));
		ca[l++]=tem;
		for(int i=m-2;i>=0;i--)
		{
			if(k&&i+1==k)
			{
				ca[l++]=-1;
				ca[l++]=a[i];
				k--;
				continue;
			}
			if(k&&tem+a[i]>x)
			{
				ca[l++]=-1;
				ca[l++]=a[i];
				k--;
				tem=a[i];
			}
			else
			{
				ca[l++]=a[i];
				tem+=a[i];
			}	
		}
		for(int i=l-1;i>0;i--)
		{
			if(ca[i]==-1)
			cout<<"/ ";
			else
			cout<<ca[i]<<' ';
		}
		cout<<ca[0]<<endl;
	} 
	return 0;
}