您的位置:首页 > 编程语言 > C语言/C++

C++——NOIP模拟题——装果子

2017-04-22 15:00 549 查看


装果子


题目描述

果园里有 n 颗果树,每棵果树都有一个编号 i(1≤i≤n)。小明已经把每棵果树上的果子都摘下来堆在了这棵树的下方,每棵树下方的果子体积为 ai。

现在小明将拿来 m 个袋子把这些果子都装进袋子里。每个袋子的体积为 v 。

小明会按照如下规则把果子装进袋子里: 

(a) 从第 1 棵果树开始装起,由 1 到 n 一直装到第 n 棵果树。

(b) 如果这棵果树下的果子能全部装进当前这个袋子,就装进去;如果不能,就关上当前这个袋子,打开一个新的袋子开始装。

小明希望在能把所有果子都装进袋子里的前提下,v 尽量小。m 个袋子并不一定都要装进果子。


输入格式

输入第 1 行,包含两个整数 n 和 m 。

输入第 2 行,包含 n 个整数 ai 。


输出格式

输出仅一行,表示最小的 v 。


样例数据 1

输入

3 3 

1 2 3
输出

3


样例数据 2

输入

5 3 

1 3 6 1 7
输出

7


样例数据 3

输入

6 3 

1 2 1 3 1 4
输出

4


备注

【样例解释1】

每个袋子的体积为 3 即可。前 2 棵果树的果子装在第一个袋子里,第 3 棵果树的果子装在第二个袋子里。第三个袋子不用装了。
【样例解释2】

每个袋子的体积为 7 即可。前 2 棵果树的果子装在第一个袋子里,此时第一个袋子已经装了 4 单位体积的果子,第 3 棵果树的果子装不下了,所以装进第二个袋子里,第 4 棵果树的果子刚好装进第二个袋子,第 5 棵果树的果子装进第三个袋子里。
【样例解释3】

每个袋子的体积为 4 即可。前 3 棵果树的果子装在第一个袋子里,第 4~5 棵果树的果子装在第二个袋子里,第 6 棵果树的果子装在第三个袋子里。
【数据范围】

对于40%的数据,0<m≤n≤1,000,0<ai≤1,000;

对于70%的数据,0<m≤n≤100,000,0<ai≤100,000;

对于100%的数据,0<m≤n≤100,000,0<ai≤1,000,000,000。

解题报告:

关键词:二分 

二分V,然后每次 O(n) 判断一遍。如果可以装进全部的果子就二分左区间,如果不行就二分右区间。

开 long long 是必然的。

时间复杂度:O(nlog21014) 
#include<iostream>
#include<cstdio>
long long a[100001];
long long mmp,n,m;
inline long long readint()
{
long long i=0,f=1;
char ch;
for(ch=getchar();ch<'0'||ch>'9';ch=getchar());
for(;ch>='0' && ch<='9';ch=getchar())
i=(i<<3)+(i<<1)+ch-'0';
return i*f;
}
inline bool f(long long x)
{
if(x<mmp) return false;
long long ct=1,cn=0,i;
for(i=1;i<=n;++i)
if((cn+=a[i])>x)
{
cn=a[i];
++ct;
}
return ct<=m;
}
int main()
{
static long long l,r=1e14,mid;
register int i;
n=readint();
m=readint();
for(i=1;i<=n;++i)
{
a[i]=readint();
if(a[i]>=mmp) mmp=a[i];
}
while(l<=r)
{
if(f(mid=l+r>>1)) r=mid-1;
else l=mid+1;
}
printf("%I64d\n",l);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言