题目地址:P1182 数列分段 Section II - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
该题目所求为每段和最大值最小为多少,即最优解问题,联想到二分做法。
但问题是怎样去二分?即初始边界
由题目想到,如果极端一点,每个数都分一个组或者把所有数都放在一个组,那么最大值就是我们输入的数列中的最大值和数列求和,那么这就是左边界和右边界了。
这样后我们只要写个判断函数,判断是否合适。
对于每一个组来说它可以有任意个数但是又不能没有,所以这里运用一点贪心思想,题目要求最大值,那么按照常规的二分思想,假设我们的mid值为合适的解(即满足题目要求但是可能不是最优的),那么就遍历题目所给的数列并求和,当它大于或等于我们的mid就分个组,并记数。
遍历完之后,判断所记的数与题目所给的分组数是否相同,相同则说明满足题目要求,但是可能还有更优解(比这个值还要小)那我们就将右边界赋值为mid-1,如果大于说明mid太小了,就将左边界赋值为mid+1,如果小于说明mid太大,就将右边界赋值为mid-1
本题基本思路就是这样。
下面是代码
#洛谷P1182 数列分段 Section II
def check(mid):
ans = 1
sen = 0
for i in range(n):
if sen+d[i] <= mid:
sen += d[i]
else:
sen = d[i]
ans += 1
if ans <= m:
return True # r = mid-1
else:
return False
n,m = map(int,input().split())
d = list(map(int,input().split()))
l = max(d)
r = sum(d)
result = 0
while l<=r:
mid = (l+r)//2
if check(mid):
r = mid-1
result = mid
else:
l = mid+1
print(result)