【算法30】从数组中选择k组长度为m的子数组,要求其和最小
原题链接:codeforce 267 Div2 C
问题描述:
给定长度为n的数组a[],从中选择k个长度为m的子数组,要求和最大。
形式描述为:选择$k$个子数组[$l_1$, $r_1$], [$l_2$, $r_2$], ..., [$l_k$l1, $r_k$] (1 ≤ $l_1$ ≤$r_1$ ≤$l_2$ ≤ $r_2$ ≤... ≤$l_k$ ≤ $r_k$ ≤ n; $r_i-r_i+1$), 使得$\sum_{i=1}^{k}\sum_{j=l_i}^{r_i}p_j$
问题分析:
【思路1】先从简单粗暴的方法入手,怎么办?寻找所有的k个长度为m的子数组,然后选择其中和最小的。第一个长度为m的子数组开始位置可能为0...(k-1)*m,然后第二个子数组的下标?第三个子数组下标?太复杂了而且时间复杂度肯定超高,不能忍,换个方法吧。
【思路2】再看一下问题,要求和最大,求最值问题十有八九都是DP问题,试试吧。DP题目子问题怎么定义是关键,然后这东西基本只能靠经验了(嗯,算法导论上就是这么说的)。从后往前考虑,那么对于最后一个元素,只有两种情况,被选中到子数组中或者没有被选到子数组中。如果被选中,那么首先计算最后m个元素的和,剩下的问题就化为从前面长度为n-m的数组中选择k-1组和最大的子数组。如果没选中最后一个,也好办,直接转化为从前面n-1个元素中选择k组和最大的子数组。分析后我们有:
子问题定义: dp[i][j] = 从前i个元素中选择j个子数组的最大和
状态转移方程: dp[i][j] = max(dp[i-1][j], dp[i-m][j-1] + sum(a[i-m]...a[i-1]))
初始条件: dp[0][j] = 0; dp[i][0] = 0; if (i < j * m) dp[i][j] = 0;
AC代码如下:
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <algorithm> 5 #include <functional> 6 #include <numeric> 7 using namespace std; 8 9 int main() 10 { 11 int n, m, k; 12 cin >> n >> m >> k; 13 14 vector<int> v(n, 0); 15 for (int i = 0; i < n; ++i) 16 { 17 cin >> v[i]; 18 } 19 20 // dp[i][j] = choose j pairs integers from the first i elements 21 // Then base on the ith is chosen or not, there are two case: 22 // not choose ith element, the dp[i][j] = dp[i-1][j] 23 // choose ith element, the dp[i][j] = dp[i-m][j-1] + sum(a[i-1]...a[i-m]) 24 // so dp[i][j] = max(dp[i-1][j], dp[i-m][j-1] + sum(a[i-1]...a[i-m]) 25 // base case: assert (i >= j * m) if not 0 dp[i][j] = 0 26 // the problem is equal to find dp[n][k] 27 28 vector<vector<long long> > dp(n+1, vector<long long>(k+1, 0)); 29 30 // base case 31 for (int i = 0; i < n + 1; ++i) 32 { 33 for (int j = 0; j < k + 1; ++j) 34 { 35 if (i < j * m) 36 { 37 dp[i][j] = 0; 38 } 39 } 40 } 41 42 // bottom to up 43 for (int i = 1; i < n + 1; ++i) 44 { 45 for (int j = 1; j < k + 1; ++j) 46 { 47 if (i >= j * m) 48 { 49 long long lastPairSum = accumulate(v.begin() + i - m, v.begin() + i, 0LL); 50 dp[i][j] = max(dp[i-1][j], dp[i-m][j-1] + lastPairSum); 51 } 52 53 } 54 } 55 56 long long ans = dp[n][k]; 57 cout << ans << endl; 58 return 0; 59 }
注意点:
这道题目很简单的,为什么要记录下来呢,因为我用了int,出现了overflow,想了半天也没想明白到底错在哪里了,脑子真是瓦特啦,记下来以免重蹈覆辙。
转载于:https://www.cnblogs.com/python27/p/3984061.html
【算法30】从数组中选择k组长度为m的子数组,要求其和最小相关推荐
- 找出数组中第k大和第m大的数字之和
找出数组中第k大和第m大的数字之和 说明:定义一个函数,接受三个参数getMaxNumber(array,k,m){},找出第k大和第m大的数字之和.重复的数组也需要计算 比如:[1,3,4,5,4, ...
- 算法导论:快速找出无序数组中第k小的数
题目描述: 给定一个无序整数数组,返回这个数组中第k小的数. 解析: 最平常的思路是将数组排序,最快的排序是快排,然后返回已排序数组的第k个数,算法时间复杂度为O(nlogn),空间复杂度为O(1). ...
- 算法12--topK求一个数组中第k大的数
求一个数组中第k大的值 解法一: 建立一个k个元素的最大堆,首先将数组中前k个元素放入堆中,此时堆顶元素为第k大的元素,后面继续遍历数组,比较堆顶元素与数组中元素值,当数组中元素小于堆顶元素时,将堆顶 ...
- 求数组中第k个最小数
一.问题描述 给定一个数组,数组中的数据无序,在一个数组中找出其第k个最小的数,例如对于数组x,x = {3,2,1,4,5,6},则其第2个最小的数为2. 二.解题思路 本算法跟快排的思想相似,首先 ...
- 结对开发项目:求整数数组中连续子数组和的最大值
小组成员:安娜 王鑫楠 题目二:求整数数组中连续子数组和的最大值. 1.分析过程: 题目收到后,前五分钟设计算法,首先也想到是不是一次遍历可以解决,考虑了一下觉得难度有点大最后还是果断放弃.我刚开始的 ...
- 寻找无序数组中第k大的数
对于一个无序的数组,怎样找到其中第k大的数呢?下面总结几种方法. 1.直接排序法 使用常见的归并排序.堆排序等算法对数组进行排序,然后找到第k大的数.排序算法的时间复杂度为O(nlogn),所以算法总 ...
- java查找第k大的数字_查找数组中第k大的数
问题: 查找出一给定数组中第k大的数.例如[3,2,7,1,8,9,6,5,4],第1大的数是9,第2大的数是8-- 思考:1. 直接从大到小排序,排好序后,第k大的数就是arr[k-1]. 2. ...
- 线性时间复杂度求数组中第K大数
求数组中第K大的数可以基于快排序思想,步骤如下: 1.随机选择一个支点 2.将比支点大的数,放到数组左边:将比支点小的数放到数组右边:将支点放到中间(属于左部分) 3.设左部分的长度为L, 当K &l ...
- 左神算法:未排序正数数组中累加和为给定值的最长子数组长度(Java版)
本题来自左神<程序员代码面试指南>"未排序正数数组中累加和为给定值的最长子数组长度"题目. 题目 牛客OJ:未排序数组中累加和为给定值的最长子数组长度 题解 本文提供的 ...
最新文章
- Oracle的登陆问题和初级学习增删改查(省略安装和卸载)
- PAT甲级1066 Root of AVL Tree (25分):[C++题解]建立平衡树(AVL树)
- python计算tfidf sklearn计算
- Linux下unlink函数的使用
- 【视频课】如何掌握好深度学习之视频分类与行为识别?这一门课足矣!
- 关于ejabberd限制单点登录
- C语言size_t和size_type比较
- SAP Spartacus CmsComponentConnector
- python调用simulink_使用Python从dbc文件中提取simulink建模数据定义
- 建议把英语改成选修的计算机老师,越来越多的人建议高中将英语作为选修课,而非必修课,您认同吗?...
- 关于 libpcap的安装
- atexit函数详解
- JavaScript 类式继承与原型继承
- String转LocalDateTime
- 2.Windows 界面技术发展现状
- Java原生-实现SHA256算法【工具类】
- Javashop B2B2C 系统之社区团购商城
- 去除AuotoCAD学生版水印的办法
- 安卓系统加速_安卓系统用户玩LOL手游用网易UU加速器加速被拦截解决方案
- android 按钮救星,按键救星下载-按键救星专业版(Button Savior Pro) 安卓版v2.1.1-PC6安卓网...
热门文章
- android 自定义打包,android 自定义打包后的app名称
- matlab传递函数参数辨识,基于matlab/Simulink的参数辨识
- telnet 22正常 ssh无法连接_Telnet咋就不安全了呢?带你来看用户名和密码
- php pg connect,pg_connect
- python中的模块原则_python 的模块与包
- Tex2Word vs Word2Tex
- 洛谷 P1206 [USACO1.2]回文平方数 Palindromic Squares
- BZOJ 3119 Book (贪心+数学推导)
- unity怎么实现人脸追踪_景区人脸识别解决方案 人脸识别过闸机怎么实现
- python 分班_Python学习作业一