详解数组分段和最大值最小问题(最小m段和问题)
数组分段和最大值最小问题(最小m段和问题)
问题描述
给定n个整数组成的序列,现在要求将序列分割为m段,每段子序列中的数在原序列中连续排列。如何分割才能使这m段子序列的和的最大值达到最小?
清洁工:假设有n个房间,清洁每个房间耗时用一个数组表示,10、20、30、40、50、60、70、80、90,安排m个清洁工,将连续的房间分成m份,每部分耗时求和,其最大值为此种分法的总耗时。求最快的耗时是多少。例如3个清洁工的话,10 20 30 40 50 | 60 70 | 80 90,此时是最快的,耗时为170。
装桶:把数据按顺序装入桶中,m即是给定的桶数,问桶的容量至少应该为多少才能恰好把这些数装入m个桶中
思路
先考虑最简单的情况,假设有 \(1\) 个数,只有一个桶,\(m=1\):至少需要容量为该数的值;
- 如果 \(n\) 个数,只有一个桶,\(m=1\):至少需要容量为 \(n\) 个数之和;
- 如果 \(2\) 个数,两个桶,\(m=2\):至少需要容量为两数之间最大值
- 如果 \(t\) 个数,两个桶,\(m=2\) 呢?
我们将 \(t\) 个数划分为两份,随机选一个划分位置 \(k\)
10, 20, 30, 40, | 50, 60, 70, 80, 90
就变成两部分: \(k\) 个数分到 1 个桶;\(t-k\) 个数分到一个桶
最少所需容量为 \(f(t,2) = min\{max[f(k,1),f(t-k,1)]\},1\leq k < t\),其中 \(f(t-k,1)\) 表示后 \(t-k\) 个数之和,表示为\(f(t-k,1) = f(t,1)-f(k,1)\)
- 现在考虑 \(n\) 个数,\(m\) 个桶:
我们同样将 \(n\) 个数划分为两份,即前 \(m-1\) 个桶和最后 \(1\) 个桶,随机选一个划分位置 \(k\):
\]
可以使用递归求解了,但是太耗时。我们使用动态规划填表就可以搞定了:
\]
可以用行表示对应的数字,列表示桶的数目,对1,2,3,4,5,两个桶:
| 桶1 | 桶2 | |
|---|---|---|
| 1 | 1 | 1 | 
| 2 | 3 | 2 | 
| 3 | 6 | 3 | 
| 4 | 10 | 7 | 
| 5 | 15 | 9 | 
coding:
#---python
#动态规划
# dp[i][j] = min(max(dp[k][j-1],dp[i][1]-dp[k][1]))
def dp_minMsum(nums,m):
    n = len(nums)
    dp = [[float('inf')]*(m+1) for _ in range(n+1)]
    #初始化
    for i in range(1,n+1):#只有一个桶
        dp[i][1] = sum(nums[:i])
    for j in range(1,m+1):#只有一个数
        dp[1][j] = nums[0]
    for i in range(2,n+1):
        for j in range(2,m+1):
            for k in range(1,i+1):
                dp[i][j] = min(dp[i][j],max(dp[k][j-1],dp[i][1]-dp[k][1]))
    return dp[-1][-1]
测试下:
>>> nums = [5,3,2,4,1]
>>> m = 2
>>> dp_minMsum(nums,m)
8
>>> nums = [10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> m=3
>>> dp_minMsum(nums,m)
170
复杂度
时间复杂度:\(O(MN^2)\)
空间复杂度:\(O(NM)\)
二分查找优化
给定当前的桶容量,可以计算出需要的最少桶数:
如果需要的桶数量大于给定的桶数量k,说明桶容量太小了,增大容量;
如果计算需要的桶数量小于等于k,说明桶容量可能大了(也可能正好是要找的最小桶容量)
- 在给定容量时,求需要桶数
- 二分搜索桶容量
coding:
#---python
#根据桶容量进行二分查找对应的桶数
def bs_minMsum(nums,m):
    low = max(nums)#容量下界 最大元素
    high = sum(nums)#容量上界 元素和
    while low < high:
        mid = low+(high-low)//2
        buckets = get_buckets(nums,mid)
        if buckets <= m:#该容量下桶数 小于 给定桶数。减小容量
            high = mid
        else:           #桶数 大于 给定桶数。增大容量
            low = mid +1
    return low
def get_buckets(nums,volume):
    buckets = 1
    ans = 0
    for num in nums:
        ans += num
        if ans > volume:
            buckets += 1
            ans = num
    return buckets
复杂度
时间复杂度:\(O(Nlog(\sum n))\),\(\sum n\) 为给定数组的元素和
空间复杂度:\(O(1)\)
详解数组分段和最大值最小问题(最小m段和问题)的更多相关文章
- linux进程的堆栈空间_代码段(指令,只读)、数据段(静态变量,全局变量)、堆栈段(局部变量)、栈【转】
		转自:http://blog.csdn.net/gongweijiao/article/details/8207333 原文参见:http://blog.163.com/xychenbaihu@yea ... 
- 3532: [Sdoi2014]Lis 最小字典序最小割
		3532: [Sdoi2014]Lis Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 865 Solved: 311[Submit][Status] ... 
- 黄聪:中国大陆的所有IP段,中国电信所有IP段、中国铁通所有IP段、中国网通所有IP段。
		中国大陆的所有IP段,中国电信所有IP段.中国铁通所有IP段.中国网通所有IP段. 中国大陆的所有IP段: 47.153.128.0 47.154.255.25558.14.0.0 58.25.255 ... 
- 紫书 例题 11-2 UVa 1395(最大边减最小边最小的生成树)
		思路:枚举所有可能的情况. 枚举最小边, 然后不断加边, 直到联通后, 这个时候有一个生成树.这个时候,在目前这个最小边的情况可以不往后枚举了, 可以直接更新答案后break. 因为题目求最大边减最小 ... 
- 【BZOJ-2229】最小割         最小割树(最大流+分治)
		2229: [Zjoi2011]最小割 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1565 Solved: 560[Submit][Status ... 
- BZOJ2229[Zjoi2011]最小割——最小割树
		题目描述 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分 ... 
- POJ 3522 ——Slim Span——————【最小生成树、最大边与最小边最小】
		Slim Span Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 7102 Accepted: 3761 Descrip ... 
- 【BZOJ2229】[Zjoi2011]最小割 最小割树
		[BZOJ2229][Zjoi2011]最小割 Description 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有 ... 
- 2229: [Zjoi2011]最小割(最小割树)
		Description 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中 ... 
随机推荐
- [POI2014][树形DP]FarmCraft
			题目 In a village called Byteville, there are houses connected with N-1 roads. For each pair of houses ... 
- 《深入理解 Java 虚拟机》读书笔记:线程安全与锁优化
			正文 一.线程安全 当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那 ... 
- Debug 是门艺术
			最近想结合发生在身边码农身上的一些小故事,尝试表达一个观点“Coding 是门技术,Debug 是门艺术”. 上期的分享<Coding 是门技术>主要通过引入身边 Code farmer ... 
- .gitattributes
			.gitattributes文件是一个文本文件,文件中的一行定义一个路径的若干属性.以行为单位设置一个路径下所有文件的属性,格式如下: 要匹配的文件模式 属性1 属性2 GRLF和LF CRLF,LF ... 
- vue中使用阿里图标库iconfont和在旧有的iconfont中添加新的图标
			第一步 下载样式http://www.iconfont.cn/选择图表,点击加入购物车 第二步 解压下载文件 第三步 修改文件名称 与 iconfont.css 名路径 第四步 将@font-face ... 
- 记python 链式比较的坑
			前两天,python交流群里有人问: “x”<"y"==True 这个表达式输出的是什么,脑子都没动,就觉得应该是True 居然被否定了!立马在命令行里敲了一下,准备用事实打 ... 
- 好玩Python——PIL项目实训
			PIL学习总结: 1. 2,PIL库概述: pil库可以完成图像归档和图像处理两方面功能的需求: 图像归档:对图像进行批处理,生成图像预览,图像转换格式等: 图像处理:图像基本处理,像素处理,颜色处理 ... 
- 基础类封装-pymysql库操作mysql封装
			import pymysql from lib.logger import logger from warnings import filterwarnings filterwarnings(&quo ... 
- css--->圆角设置
			1.为元素添加四个相同的圆角: 语法结构:border-radius:r: r为圆角的半径大小 eg:如下样式,给元素添加四个圆角为10px 代码如下: <!DOCTYPE html> ... 
- Python设计模式(9)-外观模式
			# /*外观模式:为外界调用提供一个统一的接口,把其他类中需要用到的方法提取# * 出来,由外观类进行调用.然后在调用段实例化外观类,以间接调用需要的# * 方法.这种方式和代理模式有异曲同工之妙.然 ... 
