【算法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代码如下:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <numeric>
using namespace std; int main()
{
int n, m, k;
cin >> n >> m >> k; vector<int> v(n, );
for (int i = ; i < n; ++i)
{
cin >> v[i];
} // dp[i][j] = choose j pairs integers from the first i elements
// Then base on the ith is chosen or not, there are two case:
// not choose ith element, the dp[i][j] = dp[i-1][j]
// choose ith element, the dp[i][j] = dp[i-m][j-1] + sum(a[i-1]...a[i-m])
// so dp[i][j] = max(dp[i-1][j], dp[i-m][j-1] + sum(a[i-1]...a[i-m])
// base case: assert (i >= j * m) if not 0 dp[i][j] = 0
// the problem is equal to find dp[n][k] vector<vector<long long> > dp(n+, vector<long long>(k+, )); // base case
for (int i = ; i < n + ; ++i)
{
for (int j = ; j < k + ; ++j)
{
if (i < j * m)
{
dp[i][j] = ;
}
}
} // bottom to up
for (int i = ; i < n + ; ++i)
{
for (int j = ; j < k + ; ++j)
{
if (i >= j * m)
{
long long lastPairSum = accumulate(v.begin() + i - m, v.begin() + i, 0LL);
dp[i][j] = max(dp[i-][j], dp[i-m][j-] + lastPairSum);
} }
} long long ans = dp[n][k];
cout << ans << endl;
return ;
}
注意点:
这道题目很简单的,为什么要记录下来呢,因为我用了int,出现了overflow,想了半天也没想明白到底错在哪里了,脑子真是瓦特啦,记下来以免重蹈覆辙。
【算法30】从数组中选择k组长度为m的子数组,要求其和最小的更多相关文章
- 选择问题(选择数组中第K小的数)
由排序问题可以引申出选择问题,选择问题就是选择并返回数组中第k小的数,如果把数组全部排好序,在返回第k小的数,也能正确返回,但是这无疑做了很多无用功,由上篇博客中提到的快速排序,稍稍修改下就可以以较小 ...
- 现在有m组n个有序数组,例如{1,2,3,4},{2,3,4,6},{1,3,5,7},在这些数组中选择第k小的数据,然后返回这个值
问题描述:现在有m组n个有序数组,例如{1,2,3,4},{2,3,4,6},{1,3,5,7},在这些数组中选择第k小的数据,然后返回这个值 思路:参照两个数组归并的过程,每次选取最小的数据进行比较 ...
- [经典算法题]寻找数组中第K大的数的方法总结
[经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26 字体:[大 中 小] 打印复制链接我要评论 今天看算法分析是,看到一个这样的问题,就是在一堆数据 ...
- 前端算法题:找出数组中第k大的数字出现多少次
题目:给定一个一维数组,如[1,2,4,4,3,5],找出数组中第k大的数字出现多少次. 例如:第2大的数是4,出现2次,最后输出 4,2 function getNum(arr, k){ // 数组 ...
- 查找数组中第k大的数
问题: 查找出一给定数组中第k大的数.例如[3,2,7,1,8,9,6,5,4],第1大的数是9,第2大的数是8-- 思考:1. 直接从大到小排序,排好序后,第k大的数就是arr[k-1]. 2. ...
- 寻找数组中第K大数
1.寻找数组中的第二大数 using System; using System.Collections.Generic; using System.Linq; using System.Text; u ...
- 一题多解(五) —— topK(数组中第 k 大/小的数)
根据对称性,第 k 大和第 k 小,在实现上,是一致的,我们就以第 k 小为例,进行说明: 法 1 直接排序(sort(A, A+N)),当使用一般时间复杂度的排序算法时,其时间复杂度为 O(N2) ...
- [LeetCode] Kth Largest Element in an Array 数组中第k大的数字
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...
- 数组中第K小的数字(Google面试题)
http://ac.jobdu.com/problem.php?pid=1534 题目1534:数组中第K小的数字 时间限制:2 秒 内存限制:128 兆 特殊判题:否 提交:1120 解决:208 ...
随机推荐
- Android模拟器内安装应用
一.通过apk安装器安装应用 1.下载apk安装器(网上随便搜一个就可以) 2.下载要测试的应用的apk,我这里下载的是微信的apk 3.打开apk安装器,点击右上角的Devices选择要安装到的设备 ...
- for循环语句个人小结
重新看了一下光盘上的用for循环写一个菱形的答案,发现了其实有几点是可以灵活运用的: 1,当定义行数的时候,也可以用相等的间断的数字隔开,比如 for(int a = 5; a >= 1; a- ...
- DOMNodeInserted监听div内容改变
$('.cw-icon .ci-count').on('DOMNodeInserted',function(){ $(".settleup-content .cont_loading&quo ...
- Proximal Algorithms
1. Introduction Much like Newton's method is a standard tool for solving unconstrained smooth minimi ...
- 2018.10.14 loj#6011. 「网络流 24 题」运输问题(费用流)
传送门 费用流入门题. 直接按照题意模拟. 把货物的数量当做容量建边. 然后跑一次最小费用流和最大费用流就行了. 代码: #include<bits/stdc++.h> #define N ...
- UVa 12230 && HDU 3232 Crossing Rivers (数学期望水题)
题意:你要从A到B去上班,然而这中间有n条河,距离为d.给定这n条河离A的距离p,长度L,和船的移动速度v,求从A到B的时间的数学期望. 并且假设出门前每条船的位置是随机的,如果不是在端点,方向也是不 ...
- ArcGIS Desktop python Add-in 创建一个插件
1)创建一个项目 首先创建一个插件项目,本节介绍如何利用向导创建一个插件项目. 创建任何一个ArcGIS插件产品的过程都是一样的. 创建一个Python插件项目包括2个步骤: a) 选择一个插件项目文 ...
- 整数重复的第n位计算公式
513不停的重复形成513513513....,求第n位是几的计算公式.
- 记录:Web相关政策之备案号、视频播放
(一)备案号链接: 服务器在国内的网站受工信部监管,并受其颁布的<管理办法>约束.根据<互联网信息服务管理办法>及<非经营性互联网信息服务备案管理办法>的法律法规, ...
- 一个用css写出来的下拉菜单
1 <style> 2 /* css*/ 3 #body{ 4 float: left; 5 } 6 #xialakuang{ 7 background-color:#f9f9f9; 8 ...