Live2d Test Env

ZOJ 2002 Copying Books 二分 贪心

                                   传送门:Zoj2002

题目大意:从左到右把一排数字k分,得到最小化最大份,如果有多组解,左边的尽量小。

思路:贪心+二分(参考青蛙过河)。

方向:从右向左。

注意:有可能最小化时不够k分。如

                                    3 3
                           1 2 3
  k分得到最小化的最大值是3,分组却只能分两个组。
   错误结果是 1 2 / 3.正确结果是1 / 2 / 3
  因此要从左到右补齐‘/’


#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<memory.h>
using namespace std;
int n,k;
int a[510];
int b[510];
int used;
void _update()
{
	memset(b,0,sizeof(b));//开始把0写成false了。。。。尴尬
	memset(a,0,sizeof(a));
}
bool  _judge(long long  v)
{
     long long  temp;
	 used=0;
     int i=n;
     while(i>=1)
     {
		 temp=0;
		 used++;
		 while(temp+a[i]<=v){
		   temp+=a[i];
		   i--;
		   if(i<1) break;
		 }
	  }
	 if(used<=k) return true;
	 return false;
}
void _Cout(long long  v)
{
     long long  temp;
     int i=n;
     used=0;
     while(i>=1)
     {
		 temp=0;
		 used++;
		 while(temp+a[i]<=v){
		   temp+=a[i];
		   i--;
		  }
		  b[i]=1;
	  }
	 for(i=1;i<n;i++)
	 {
		 cout<<a[i]<<" ";
		 if(b[i]) cout<<"/ ";
		 else if(used<k) {        //    补齐
				cout<<"/ ";
				used++;
		 }
	 }
	 cout<<a[n]<<endl;
}

int main()
{
	
	int i,T;
	cin>>T;
	while(T--)
	{
	  _update();
	  cin>>n>>k;
	  long long  Max=0,M=0;
	  for(i=1;i<=n;i++) {
	    cin>>a[i];
	    M+=a[i];
	    if(a[i]>Max) Max=a[i];
	  } 
	  long long  L=Max,R=M,mid;
	  while(L<R){
	    mid=(L+R)/2;
	    if(_judge(mid)) R=mid;
	    else L=mid+1;
	 }
	 _Cout(R);
	}
	return 0;
}






posted @ 2017-09-27 21:06  nimphy  阅读(107)  评论(0编辑  收藏  举报