模拟赛 工资(时限1000ms 内存256MB)

聪哥在暑假参加了打零工的活动,这个活动分为n个工作日,每个工作日的工资为Vi。有m个结算工钱的时间,聪哥可以自由安排这些时间,也就是说什么时候拿钱,老板说的不算,聪哥才有发言权!(因为聪哥是土豪,他是老板的老板)

聪哥不喜欢身上一次性有太多的钱,于是他想安排一下拿钱的时间,使他一次性拿的钱中最大的最小。(最后一天一定要领钱)

输入

第一行 2个数 n,m

接下来n行,每行一个数,代表Vi.

输出

最小的最大钱数。

样例输入

7 5

100

400

300

100

500

101

400

样例输出

500

 

样例说明

100 400//300 100//500//101//400//

“//”表示老大要去拿钱。

 

数据范围

20%  1<=n<=20

另 20%  1<=n<=50,Vi的和不超过1000

100% 1<=n<=100,000,m<=n,Vi<=10,000

题解

光看问法就是明显的二分……

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,a[100002],sum;
void init()
{
	scanf("%d%d",&n,&m);
	int i;
	for(i=1;i<=n;i++)
	   {scanf("%d",&a[i]);
	    sum=sum+a[i];
	   }
	
}
bool check(int x)
{
	int i,ct=0,s=0;
	for(i=1;i<=n;i++)
	   {if(a[i]>x) return false;
		s+=a[i];
		if(s>x) {ct++; s=a[i];}
	   }
	ct++;
	if(ct<=m) return true;
	else return false;
}
void work()
{
	int l=0,r=sum,ans,mid;
	while(l<=r)
	   {mid=(l+r)>>1; //printf("%d\n",mid);
	    if(check(mid)) {ans=mid; r=mid-1;}
	    else l=mid+1;
	   }
	printf("%d\n",ans);
}
int main()
{
	freopen("money.in","r",stdin);
	freopen("money.out","w",stdout);
	init(); work();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值