摘枇杷
时间限制:
2000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
理工学院的枇杷快熟了,ok,大家都懂得。而且大家都知道,学校的枇杷树都是一列一列的。现在小Y同学已经在筹划怎么摘枇杷了。现在我们假设有一列枇杷树,而且每棵枇杷树上枇杷果的数量小Y都已经知道了。
假设现在有n棵枇杷树,小Y可以把这n棵枇杷树分成m组,每组枇杷果的数量是这组内每棵枇杷树上枇杷果数量的和。注意,每组的枇杷树必须是连续的。(每组最少1棵树,最多n棵树)。小Y把枇杷往寝室拿的时候是一组一组拿的,所花费的力气等于这m组中枇杷果最多的那组枇杷果的数量。现在小Y想花尽量少的力气把这些枇杷果拿回寝室。
-
输入
-
多组测试数据,以EOF结束(<= 100组)
每组测试数据第一行有两个数n(n <= 1000)和m(1 <=m <= n)
第二行有n个数,分别代表每颗树上枇杷果的数量
输出
- 输出小Y同学所花费的最小的力气,每个结果占一行。 样例输入
-
3 2 1 2 3 7 5 1 4 3 1 5 2 4
样例输出
-
3 5
解题思路:这题第一感觉是dp,dp[i][j]表示前i个果子分成j组的最小力气,然后TLE一发,然后想了好久的数据结构去优化它但是想不出来,然后看到讨论区的提示,瞬间顿悟,这题完全可以二分答案+贪心策略,因为只需要找到最大的分组即可,完全没必要用dp。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 1005; int n,m; int num[maxn]; bool check(int limit) { int i = 1,sum = 0,cnt = 1; while(i <= n && cnt <= m) { if(sum + num[i] > limit) { sum = 0; cnt++; continue; } sum += num[i]; i++; } return i > n && cnt <= m; } int main() { int l,r,mid; while(scanf("%d %d",&n,&m)!=EOF) { l = r = 0; for(int i = 1; i <= n; i++) { scanf("%d",&num[i]); r += num[i]; } int ans; while(l <= r) { mid = (l + r) >> 1; if(check(mid)) { ans = mid; r = mid - 1; } else l = mid + 1; } printf("%d\n",ans); } return 0; }
-
多组测试数据,以EOF结束(<= 100组)