原题链接: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, );
  15. for (int i = ; 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+, vector<long long>(k+, ));
  29.  
  30. // base case
  31. for (int i = ; i < n + ; ++i)
  32. {
  33. for (int j = ; j < k + ; ++j)
  34. {
  35. if (i < j * m)
  36. {
  37. dp[i][j] = ;
  38. }
  39. }
  40. }
  41.  
  42. // bottom to up
  43. for (int i = ; i < n + ; ++i)
  44. {
  45. for (int j = ; j < k + ; ++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-][j], dp[i-m][j-] + lastPairSum);
  51. }
  52.  
  53. }
  54. }
  55.  
  56. long long ans = dp[n][k];
  57. cout << ans << endl;
  58. return ;
  59. }

注意点:

这道题目很简单的,为什么要记录下来呢,因为我用了int,出现了overflow,想了半天也没想明白到底错在哪里了,脑子真是瓦特啦,记下来以免重蹈覆辙。

【算法30】从数组中选择k组长度为m的子数组,要求其和最小的更多相关文章

  1. 选择问题(选择数组中第K小的数)

    由排序问题可以引申出选择问题,选择问题就是选择并返回数组中第k小的数,如果把数组全部排好序,在返回第k小的数,也能正确返回,但是这无疑做了很多无用功,由上篇博客中提到的快速排序,稍稍修改下就可以以较小 ...

  2. 现在有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小的数据,然后返回这个值 思路:参照两个数组归并的过程,每次选取最小的数据进行比较 ...

  3. [经典算法题]寻找数组中第K大的数的方法总结

    [经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26   字体:[大 中 小] 打印复制链接我要评论   今天看算法分析是,看到一个这样的问题,就是在一堆数据 ...

  4. 前端算法题:找出数组中第k大的数字出现多少次

    题目:给定一个一维数组,如[1,2,4,4,3,5],找出数组中第k大的数字出现多少次. 例如:第2大的数是4,出现2次,最后输出 4,2 function getNum(arr, k){ // 数组 ...

  5. 查找数组中第k大的数

    问题:  查找出一给定数组中第k大的数.例如[3,2,7,1,8,9,6,5,4],第1大的数是9,第2大的数是8-- 思考:1. 直接从大到小排序,排好序后,第k大的数就是arr[k-1]. 2. ...

  6. 寻找数组中第K大数

    1.寻找数组中的第二大数 using System; using System.Collections.Generic; using System.Linq; using System.Text; u ...

  7. 一题多解(五) —— topK(数组中第 k 大/小的数)

    根据对称性,第 k 大和第 k 小,在实现上,是一致的,我们就以第 k 小为例,进行说明: 法 1 直接排序(sort(A, A+N)),当使用一般时间复杂度的排序算法时,其时间复杂度为 O(N2) ...

  8. [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 ...

  9. 数组中第K小的数字(Google面试题)

    http://ac.jobdu.com/problem.php?pid=1534 题目1534:数组中第K小的数字 时间限制:2 秒 内存限制:128 兆 特殊判题:否 提交:1120 解决:208 ...

随机推荐

  1. The Doors(几何+最短路,好题)

    The Doors http://poj.org/problem?id=1556 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions ...

  2. models渲染字典&form表单上传文件&ajax上传文件

    {# {% for u in teacher_d.keys %}#} {# {% for u in teacher_d.values %}#} {% for k,u in teacher_d.item ...

  3. js Function 函数

    函数 var abs = function (x) { if (x >= 0) { return x; } else { return -x; } }; 函数体内部的语句在执行时,一旦执行到re ...

  4. 搭建事务管理转账案例的环境(强调:简化开发,以后DAO可以继承JdbcDaoSupport类)

    1. 步骤一:创建WEB工程,引入需要的jar包 * IOC的6个包 * AOP的4个包 * C3P0的1个包 * MySQL的驱动包 * JDBC目标2个包 * 整合JUnit测试包2.步骤二:创建 ...

  5. Html的Padding,Margin自己理解图

    Html的Padding,Margin自己理解图.

  6. bootstrap下modal模态框中webuploader控件按钮异常(无法点击)问题解决办法【转】

    http://bbs.csdn.net/topics/391917552 具体如下:   $(function () {         var _$modal = $('#MyModal');    ...

  7. Nginx下SSL证书设置和反向代理

    上来就贴代码: server { listen ; server_name **.****.net; #填写绑定证书的域名 ssl on; ssl_certificate /opt/nginx-/co ...

  8. 结构体的sort【防止遗忘w】

    #include<iostream> #include<algorithm> using namespace std; int n; struct jie { int num; ...

  9. laravel中的old()函数

    1.控制器 2.模板

  10. Mysql 查看表结构的命令

    创建数据库create database abc; 显示数据库 show databases; 使用数据库 use 数据库名; 直接打开数据库 mysql -h localhost -u root - ...