YYHSOI模拟赛题解(T1装果子)

题目描述

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

现在小明将拿来m个袋子把这些果子都装进袋子里。每个袋子的体积为v。小明会按照如下规则把果子装进袋子里:

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

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

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

输入

输入文件名为fruit.in

输入第1行,包含两个整数nm

第2行,包含n个整数ai

输出

输出文件名为fruit.out

输出仅1行,表示最小的v

样例输入

fruit.in 3 3 1 2 3 fruit.out 3 fruit.in 5 3 1 3 6 1 7 fruit.out 7 fruit.in 6 3 1 2 1 3 1 4 fruit.out 4

样例输出

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

提示

【数据范围】


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


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


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

 

这一道题目我们会发现一个性质,就是说如果对于一个V它是可行的,那么V+1一定可行,但是V-1可能可行,又因为题目中需要的是尽可能小的V,所以如果对于一个V是可行的,我们只要检查小于等于V中的数是否合法。同理如果对于一个V是不可行的,那么V+1可能可行,V-1一定不可行。所以如果一个V是不可行的,我们只要检查查找比它大的V就行了。而检验一个V是否可行,我们可以线扫一遍可以得出对于V而言,它所需要的袋子数量。而寻找V,我们用到的就是二分答案(由前面的性质可得)。所以时间复杂度O(N*log(MaxSum))合情合理。

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 
 9 int N,M;
10 long long a[1000005];
11 
12 bool check(long long X)
13 {
14     long long tmp=0;
15     int num1=1;
16     for (int i=1; i<=N; i++)
17     {
18         tmp+=a[i];
19         if (tmp > X)
20         {
21             tmp=a[i];
22             num1++;
23         }
24         if (X < a[i])
25         {
26             return false;
27         }
28     }
29     if (num1 <= M) return true;
30     else return false;
31 }
32 
33 int main()
34 {
35     scanf("%d%d",&N,&M);
36     long long r=-1;
37     for (int i=1; i<=N; i++)
38     {
39         scanf("%lld",&a[i]);
40         r=max(r,a[i]);
41     }
42     long long l=r; r=r * N;
43     while (l < r)
44     {
45         long long mid=(l + r) / 2;
46         if (check(mid)) r=mid;
47         else l=mid+1;
48     }
49     printf("%lld\n",l);
50     return 0;
51 }
Show My Ugly Code
 
原文地址:https://www.cnblogs.com/TUncleWangT/p/7055116.html