【小米2018-09-20在线笔试】最优分割

版权声明:本文为阿木寺的原创文章,未经本人允许不得转载。 https://blog.csdn.net/amusi1994/article/details/82793562

题目描述

依次给出n个正整数A1,A2, …,An,将n个数分割成m段,每一段内的所有数的和记为这一段的权重,m段权重的最大值记为本次分割的权重。问所有分割方案中分割权重的最小值是多少?

输入

第一行依次给出正整数n,m,单空格切分;(n<=10000,m<=10000,m<=n)

第二行依次给出n个正整数单空格切分A1,A2,…,An(Ai<=10000)

输出

分割权重的最小值

样例输入

5 3

1 4 2 3 5

样例输出

5

Hint

分割成 14 | 2 3 | 5 的时候,3段的权重都为5,得到分割权重的最小值。

在这里插入图片描述

在这里插入图片描述

题目解析

本题是LeetCode的 410. Split Array Largest Sum

Python

# Summary: 最优分割
# Author:  Amusi
# Date:    2018-09-20
# Reference: https://blog.csdn.net/XX_123_1_RJ/article/details/80470774

def splitArrays(arrays, m):
    top = sum(arrays)  # 确定上界
    down = top // m  # 确定下界 (下取整)
    size = len(arrays)
    while down <= top:
        mid = (down + top) // 2  # (下取整)
        n = m
        cnt = 0
        flag = True
        for x in range(size):
            if arrays[x] > mid:  # 如果发现数列里面有一个大于目标解的,说明真正的解在右区间,即继续搜索右区间
                flag = False
                break
            if cnt + arrays[x] > mid:  # 进行一次分割, 并初始化 n, cnt
                n -= 1
                cnt = 0
            cnt += arrays[x]  # 统计每次分割的小区间的和,
            if n == 0:  # n == 0 说明划分的段数超过了 m,说明真正的解在右区间,即继续搜索右区间
                flag = False
                break
        if flag:  # 确定下一个要搜索的区间范围
            top = mid - 1  # flag == True 说明最优解还可以再小,即在左区间里面
        else:
            down = mid + 1
    return down
 
 
if __name__ == '__main__':
    m_n = list(map(int, input("").split()))
    n,m = m_n[0], m_n[1]
    arrays = list(map(int, input("").split()))
    print(splitArrays(arrays, m))

猜你喜欢

转载自blog.csdn.net/amusi1994/article/details/82793562