ZOJ 2002 Copying Books 二分 贪心

来源:互联网 发布:淘宝客服转正评估表 编辑:程序博客网 时间:2024/05/18 18:45

                                   传送门: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;}






原创粉丝点击