数组 a 中有 M 个数 , 将 M 个数分成 N 组 , 并且每组中的数据顺序和原数组中的顺序保持一致,求 N 组中的数据之和最大为多少?

  向 dp 数组中赋初始值 ,如果 M == N ,则 dp[ i ][ i ] = dp[ i - 1 ][ i - 1 ] + a[ i ] ;

  若N为1时 ,即为求连续子串最大和问题;

  假设dp[ 1 ][ i ] ( 2 =< i <= M) 代表 与第 i 个数组成连续子串的最大和,当dp[ 1 ][ i - 1 ] < 0 时 , a[ i ] 独立作为一个子串 , 即 dp[ 1 ][ i ] = max ( dp[ 1 ][ i -1 ] + a[ i ] , a[ i ] ) ;很需要注意的一点是:dp[ 1 ][ i ] 不一定是 i 个数中连续子串的最大和。

分别求出数组中有一个数、两个数、三个数……M个数中连续子串的最大和,用dp[ i ][ 1 ] 来表示;

  若N为2时,表示将M个数分成 2 组 ,求两组数中的和最大 ;

  dp[ 2 ][ i ] ( 3 =< i <= M ) 代表 与第 i 个数组成连续子串,形成两个连续子串中,第2个子串的最大和;

  可知,第二个子串可以单独成为一段,最终形成两段,也可以和上一个段一起形成一段,最终形成两段;

所以 dp[M][N]  代表 与第M个数组成的连续子串的最大和,但不一定是 M 个数中连续子串的最大和 ;

  与第 M 个数组成连续子串时 ,第 M 个数可以与第 M-1 个数组成的子串组合,也可以独立作为一个子串 , 与  M-1 个数组成的(N-1)组连续子串中最大和组合 ,才能达到分成 N 组的效果;

  最后输出dp数组中最大值,即为 N 组中数据之和的最大值;

  

下面给出相应的代码:

#include<iostream>
using namespace std ;
#define M 100005
#define max(x,y) ((x) > (y) ? (x) : (y))
int a[ M ] , dp[ M ][ M ] ;
int main() {
int k , n ;
while(cin >> k >> n) {
int i ;
for(i = 1 ; i <= n ; i++)
cin >> a[i] ;
memset(dp,0,sizeof(dp)) ;
for(i = 1 ; i <= k ; i++) {
dp[i][i] = dp[i-1][i-1] + a[i] ;
dp[i-1][i] = max(dp[i-1][i],dp[i-1][i-1]) ;
for(int j = i + 1 ; j <= n ; j++) {
dp[i][j] = max(dp[i-1][j-1]+a[j],dp[i][j-1]+a[j]) ;
dp[i-1][j] = max(dp[i-1][j],dp[i-1][j-1]) ;
}
}
int max1 = -(1<<30) ;
for(i = k ; i <= n ; i++)
max1 = max(max1,dp[k][i]) ;
cout << max1 << endl ;
}
return 0 ;
}

  

  上面的代码空间复杂度比较高,但通过观察可以得到,依照滚动数组的思想,让dp数组的行数为2,在两行中循环,这样轻易一改,省去了很多空间:

有木有很强大!!!      思维决定到效率!!!

#include<iostream>
using namespace std ;
#define M 100005
#define max(x,y) ((x) > (y) ? (x) : (y))
int a[ M ] , dp[ 2 ][ M ] ;
int main() {
int k , n ;
while(cin >> k >> n) {
int i ;
for(i = 1 ; i <= n ; i++)
cin >> a[i] ;
memset(dp,0,sizeof(dp)) ;
int t = 0 ;
for(i = 1 ; i <= k ; i++) {
t = !t ;
dp[t][i] = dp[!t][i-1] + a[i] ;
dp[!t][i] = max(dp[!t][i],dp[!t][i-1]) ;
for(int j = i + 1 ; j <= n ; j++) {
dp[t][j] = max(dp[!t][j-1]+a[j],dp[t][j-1]+a[j]) ;
dp[!t][j] = max(dp[!t][j],dp[!t][j-1]) ;
}
}
int max1 = -(1<<30) ;
for(i = k ; i <= n ; i++)
max1 = max(max1,dp[k&1][i]) ;
cout << max1 << endl ;
}
return 0 ;
}

N 组连续子串最大和的更多相关文章

  1. ZZNU-oj-2141:2333--【O(N)求一个数字串能整除3的连续子串的个数,前缀和数组+对3取余组合数找规律】

    2141: 2333 题目描述 “别人总说我瓜,其实我一点也不瓜,大多数时候我都机智的一批“ 宝儿姐考察你一道很简单的题目.给你一个数字串,你能判断有多少个连续子串能整除3吗? 输入 多实例输入,以E ...

  2. HDU-1231 简单dp,连续子序列最大和,水

    1.HDU-1231 2.链接:http://acm.hdu.edu.cn/showproblem.php?pid=1231 3.总结:水 题意:连续子序列最大和 #include<iostre ...

  3. poj 3518 Corporate Identity 后缀数组->多字符串最长相同连续子串

    题目链接 题意:输入N(2 <= N <= 4000)个长度不超过200的字符串,输出字典序最小的最长公共连续子串; 思路:将所有的字符串中间加上分隔符,注:分隔符只需要和输入的字符不同, ...

  4. 3 Longest Substring Without Repeating Characters(最长不重复连续子串Medium)

    题目意思:求字符串中,最长不重复连续子串 思路:使用hashmap,发现unordered_map会比map快,设置一个起始位置,计算长度时,去减起始位置的值 eg:a,b,c,d,e,c,b,a,e ...

  5. 连续子序列最大和的O(NlogN)算法

    对于一个数组,例如:int[] a = {4,-3,5,-2,-1,2,6,-2}找出一个连续子序列,对于任意的i和j,使得a[i]+a[i+1]+a[i+2]+.......+a[j]他的和是所有子 ...

  6. 【ToReadList】六种姿势拿下连续子序列最大和问题,附伪代码(以HDU 1003 1231为例)(转载)

    问题描述:       连续子序列最大和,其实就是求一个序列中连续的子序列中元素和最大的那个. 比如例如给定序列: { -2, 11, -4, 13, -5, -2 } 其最大连续子序列为{ 11, ...

  7. 剑指Offer-连续子数组中的最大和

    题目 输入一个整型数组,数组里有正数也有负数.数组中的一个或连续多个整数组成一个子数组.求所有子数组的和的最大值.要求时间复杂度为 O(n). 输入 [1,-2,3,10,-4,7,2,-5] 返回值 ...

  8. 【NOIP2015提高组】子串

    https://daniu.luogu.org/problem/show?pid=2679 看到方案数问题直觉就能想到DP,考虑用f(i,j,k)表示A[1...i]取k个子串组成B[1...j]的方 ...

  9. 【NOIP】提高组2015 子串

    [题意]求从字符串A中取出k个互不重叠的非空子串顺序拼接形成B的方案数.n<=1000,m<=100,k<=m. [算法]动态规划 [题解]这题主要是将从i-l转移变成从i-1转移, ...

随机推荐

  1. HDU 1134 卡特兰数 大数乘法除法

    Problem Description This is a small but ancient game. You are supposed to write down the numbers 1, ...

  2. Quartz 2D - 图形上下文(Graphics Contexts)

    一个Graphics Context表示一个绘制目标.它包含绘制系统用于完成绘制指令的绘制参数和设备相关信息.Graphics Context定义了基本的绘制属性,如颜色.裁减区域.线条宽度和样式信息 ...

  3. TreeSet类的排序问题

     http://www.cnblogs.com/lixiaolun/archive/2012/12/25/2832775.html TreeSet支持两种排序方法:自然排序和定制排序.TreeSet默 ...

  4. Algorithms 4th - 1.1 Basic Programming Model - CREATIVE PROBLEMS

    欢迎交流 1.1.26 public class TestApp { public static void main(String[] args) { int a = StdIn.readInt(); ...

  5. BZOJ 3875: [Ahoi2014]骑士游戏

    d[i]表示消灭i所需的最小体力值, d[i] = min(S[i], K[i]+Σd[x]), Σd[x]表示普通攻击而产生的其他怪兽. 因为不是DAG, 所以用个队列类似SPFA来更新答案. -- ...

  6. Linux学习之nl命令

    nl命令在linux系统中用来计算文件中行号.nl 可以将输出的文件内容自动的加上行号!其默认的结果与 cat -n 有点不太一样, nl 可以将行号做比较多的显示设计,包括位数与是否自动补齐 0 等 ...

  7. mysql 全文检索的匹配问题

    开发过程中碰到一个关于mysql 全文检索的问题,控制台打印的SQL语句拿到数据库里执行,结果不对.后来发现原来是少了双引号.下面是网上找到的资料,我是看到这个才意识到自己的问题. 这是之前在数据库执 ...

  8. OC语法10——@protocol协议,

    参考资料:博客 @protocol,协议: OC中protocol的含义和Java中接口的含义是一样的,它们的作用都是为了定义一组方法规范. 实现此协议的类里的方法,必须按照此协议里定义的方法规范来. ...

  9. MAC环境下生成Apple证书教程

    在MAC操作系统下,生成Apple证书比较简单,全图形化操作. 一.使用Keychain Access(钥匙串访问) MAC操作系统对证书的处理都采用了“Keychain Access”(中文系统名为 ...

  10. C/C++招聘的一些感受和经验【转】

    找工作本人认为最重要的就是前期准备了.     首先.简历一定要写的切合主题.招聘单位要的是你的技能,这个只要大概能符合就可以,关键他们需要的是你的开发经验,一定要在简历中完美的体现出你之前所参与的项 ...