数组分段和最大值最小问题(最小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\):

\[f(n,m) = min\{max[f(k,m-1),f(n-k,1)]\},1\leq k < n
\]

可以使用递归求解了,但是太耗时。我们使用动态规划填表就可以搞定了:

\[f(i,j) = min\{max[f(k,j-1),f(i,1)-f(k,1)]\},1\leq k < n
\]

可以用行表示对应的数字,列表示桶的数目,对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段和问题)的更多相关文章

  1. linux进程的堆栈空间_代码段(指令,只读)、数据段(静态变量,全局变量)、堆栈段(局部变量)、栈【转】

    转自:http://blog.csdn.net/gongweijiao/article/details/8207333 原文参见:http://blog.163.com/xychenbaihu@yea ...

  2. 3532: [Sdoi2014]Lis 最小字典序最小割

    3532: [Sdoi2014]Lis Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 865  Solved: 311[Submit][Status] ...

  3. 黄聪:中国大陆的所有IP段,中国电信所有IP段、中国铁通所有IP段、中国网通所有IP段。

    中国大陆的所有IP段,中国电信所有IP段.中国铁通所有IP段.中国网通所有IP段. 中国大陆的所有IP段: 47.153.128.0 47.154.255.25558.14.0.0 58.25.255 ...

  4. 紫书 例题 11-2 UVa 1395(最大边减最小边最小的生成树)

    思路:枚举所有可能的情况. 枚举最小边, 然后不断加边, 直到联通后, 这个时候有一个生成树.这个时候,在目前这个最小边的情况可以不往后枚举了, 可以直接更新答案后break. 因为题目求最大边减最小 ...

  5. 【BZOJ-2229】最小割 最小割树(最大流+分治)

    2229: [Zjoi2011]最小割 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1565  Solved: 560[Submit][Status ...

  6. BZOJ2229[Zjoi2011]最小割——最小割树

    题目描述 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分 ...

  7. POJ 3522 ——Slim Span——————【最小生成树、最大边与最小边最小】

    Slim Span Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7102   Accepted: 3761 Descrip ...

  8. 【BZOJ2229】[Zjoi2011]最小割 最小割树

    [BZOJ2229][Zjoi2011]最小割 Description 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有 ...

  9. 2229: [Zjoi2011]最小割(最小割树)

    Description 小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中 ...

随机推荐

  1. HBase 监控 | HBase Metrics 初探(一)

    前言:对于任意一个系统而言,做好监控都是非常重要的,HBase也不例外.经常,我们会从JMX中获取相关指标来做展示.对HBase进行监控,那这些指标是怎么生成的呢?如果你想自定义自己的监控指标又该怎么 ...

  2. STL之map与pair与unordered_map常用函数详解

    STL之map与pair与unordered_map常用函数详解 一.map的概述 map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称 ...

  3. A AK的距离

    时间限制 : - MS   空间限制 : - KB  评测说明 : 1s,128m 问题描述 同学们总想AK.于是何老板给出一个由大写字母构成的字符串,他想你帮忙找出其中距离最远的一对'A'和'K'. ...

  4. vulnhub~sunset:dusk1

    晚上闲来无事,准备做个target,结果是各种错误.在睡觉前还是没有顺利的做出来.先将TroubleSHOOTing 总结如下: 在用hydra爆破mysql的时候,发现 'MySql Host is ...

  5. 从上帝视角看Java如何运行

    JVM内存结构 可以看出JVM从宏观上可以分为 ‘内部’  及 ‘外部’  两个部分(便于记忆理解): ‘内部’包含:线程共享(公有)数据区 和 线程隔离(私有)数据区 ‘外部’包含:类加载子系统.垃 ...

  6. Lisp-02: 函数

    函数(functions) 在 Lisp 中,函数分两种:有名函数和匿名函数(lambda函数). 有名函数 defun 有名函数的标准定义格式为: (defun <name> (list ...

  7. ajax前端传递对象给后端

    前端操作如下即可:

  8. 部署mysql主从同步

                                                 mysql-day06        部署mysql主从同步 案例拓扑 • 一主.一从 – 单向复制时,建议将 ...

  9. 这些基本的 HTML5 标签你不能不知道

    HTML5元素 HTML5是HTML最新的修订版本,2014年10月由万维网联盟(W3C)完成标准制定. HTML5是用来写网页的一门标记语言. 使用的时候需要在首行声明HTML,如:<!DOC ...

  10. 2020 PHP 初级 / 基础面试题,祝你金三银四跳槽加薪 (适合基础不牢固的 PHPer)

    1.PHP 语言的一大优势是跨平台,什么是跨平台? PHP 的运行环境最优搭配为 Apache+MySQL+PHP,此运行环境可以在不同操作系统(例如 windows.Linux 等)上配置,不受操作 ...