九度1502(折半法)

题目1502:最大值最小化

时间限制:1 秒

内存限制:128 兆

特殊判题:

提交:62

解决:21

题目描述:

在印刷术发明之前,复制一本书是一个很困难的工作,工作量很大,而且需要大家的积极配合来抄写一本书,团队合作能力很重要。
当时都是通过招募抄写员来进行书本的录入和复制工作的, 假设现在要抄写m本书,编号为1,2,3...m, 每本书有1<=x<=100000页, 把这些书分配给k个抄写员,要求分配给某个抄写员的那些书的编号必须是连续的。每个抄写员的速度是相同的,你的任务就是找到一个最佳的分配方案,使得所有书被抄完所用的时间最少。

输入:

输入可能包含多个测试样例。
第一行仅包含正整数 n,表示测试案例的个数。
对于每个测试案例,每个案例由两行组成,在第一行中,有两个整数m和 k, 1<=k<=m<=500。 在第二行中,有m个整数用空格分隔。 所有这些值都为正且小于100000。

输出:

对应每个测试案例,
输出一行数字,代表最佳的分配方案全部抄写完毕所需要的时间。

样例输入:
2
9 3
100 200 300 400 500 600 700 800 900
5 4
100 100 100 100 100
样例输出:
1700
200

首先明确最小时间肯定介于均值与和之间,可以用折半法逐步缩小区间寻找答案。注意判断左右缩小区间的方法!

#include<iostream> #include<cstdio> using namespace std;

const int MAX=500+10; int a[MAX]; int n,k;

bool judge(int num) {  int i=0;  int count=0;  int tsum;  while(i<n&&count<=k)  {   count++;   tsum=0;   while(i<n&&tsum+a[i]<=num)   {    tsum+=a[i];    i++;   }  }  return count<=k; }

int main() {  int Left,Right,Sum;  int t,i;  cin>>t;  while(t--)  {   scanf("%d%d",&n,&k);   Sum=0;   for(i=0;i<n;i++)   {    scanf("%d",&a[i]);    Sum+=a[i];   }   int Left=Sum/k;   int Right=Sum;   while(Left<=Right)   {    int Mid=(Left+Right)/2;    if(judge(Mid))    {      Right=Mid-1;    // Left=Mid+1;    }    else    {     Left=Mid+1;    // Right=Mid-1;    }   }

  for(i=Right;i<=Left;i++)   {    if(judge(i))     printf("%d\n",i);   }  }  return 0; }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值