uva 714 贪心+二分

#include<bits/stdc++.h>
using namespace std;
const int maxm=500;
int k,m,p[maxm];
bool solve(int ans){
    int kr=1;
    int pre=0;
    for(int i=0;i<m;i++){
        if(pre+p[i]>ans)
            {
                kr++;
                pre=p[i];
            }
        else pre+=p[i];
            
    }
    return kr<=k;
}
// void print(int ans){
//     int pre=0;
//     int remain=k;
//     int kr=1;
//     int last[maxm];
//     for(int i=0;i<m;i++){
//         if(pre+p[i]>ans|| m-i<remain){
//             remain--;pre=p[i];last[i-1]=1;
//         }
//         else pre+=p[i];

//     }
    
//     for(int i=0;i<m-1;i++){
//         printf("%d ",p[i]);
//         if(last[i]) printf("/ ");
//     }
//     printf("%d",p[m-1]);
// }
int last[maxm]; // last[i] = 1 iff i is the last book assigned to someone
void print(long long ans) {
  long long done = 0;
  memset(last, 0, sizeof(last));
  int remain = k;
  for(int i = m-1; i >= 0; i--) {
    if(done + p[i] > ans || i+1 < remain) {
      last[i] = 1; remain--; done = p[i];
    }
    else {
      done += p[i];
    }
  }
  for(int i = 0; i < m-1; i++) {
    printf("%d ", p[i]);
    if(last[i]) printf("/ ");
  }
  printf("%d\n", p[m-1]);
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&m,&k);
        int maxn=0 ; //所有p[i]中最值,和求和
        int maxr=0;
        for(int i=0;i<m;i++){
            scanf("%d",&p[i]);
            maxn=max(maxn,p[i]);
            maxr+=p[i];
        }
        
//  贪心:每次尽量往右划分求是否可以把输入序列划分为2连续值且不超过x,其解定义为p(x);p(x)==1表示可以划分不超过x,否则不成立
//  二分:求解最佳的x值。


        while(maxn<maxr){
            int M=maxn+(maxr-maxn)/2;
            if(solve(M)){
                maxr=M;
            }
            else maxn=M+1;
        }
        // printf("%d\n",maxn);
        print(maxn);

    }

    return 0;
}

发布了239 篇原创文章 · 获赞 16 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_38662930/article/details/104239075