hdu 1024 求子序列最大和问题(动态规划+滚动数组优化)


前言

黑皮书上推的一道题,一直没理解题意,以为划分成m段就是将所有划分成m段而不能有剩余,最后才发现应该是从序列中取出m段然后使其和最大,啊这…找规律吧~
第二次编写,感觉之前理解的还不是很透彻,自己都有疑惑的东西,对读的人也一定有问题,所以返工一波~~~


一、题目

传送门
在这里插入图片描述

Sample Input:
1 3 1 2 3
2 6 -1 4 -2 3 -2 3

Sample Output:
6
8

二、题目分析解决

1.MLE情况

在这里插入图片描述
通过以上分析可以求出递推式:dp[i][j]=max(dp[i][j-1],tmp)+a[j];
tmp=max(圈1中的最大值)【循环时求出就行】
还是贴一波代码吧
(定义二维数组发生MLE)

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;

//算法思想:从n个数中,取出m段,求最大和
//定义一个dp[i][j],表示前j个数选出i组时的最大和
// 两种选择求dp[i][j],无非两种情况,一种自己一组,一种加入到i组中任意一组,
//自己一组:则此时要看前j-1个数对应的i-1个组所有结果的最大值,
//    即选取max(dp[i-1][i-1]...dp[i-1][j-1])最大值
//加入到前i组中任意一组:此时只需加上dp[i][j-1]即可
//代码走一波~
const int maxn=1000005;
int dp[100][maxn];
int a[maxn];
int n,m;
const int inf=0x7ffffff;

void solve() {

	int tmp;
	tmp=-inf;
	for(int i=1; i<=m; ++i) {

		for(int j=i; j<=n; ++j) {
			dp[i][j]=max(dp[i][j-1],tmp)+a[j];
			if(dp[i-1][j-1]>tmp) tmp=dp[i-1][j-1];//定义一个tmp存最大 
		}

	}
}

int main() {
	while(cin>>m>>n) {
		memset(a,0,sizeof(a));

		for(int i=1; i<=n; i++) {
			cin>>a[i];
		}
		memset(dp,0,sizeof(dp));
		solve();
		cout<<dp[m][n]<<endl;

	}
}



2.AC代码–滚动数组

想了一晚上,终于想明白了
在这里插入图片描述

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn=1000005;
int a[maxn];
int n,m;
const int inf=0x7ffffff;
int dp[maxn];
int premax[maxn];
void solve(){

	int tmp;
 tmp=-inf;
	for(int i=1;i<=m;++i){
		tmp=-inf; 
		for(int j=i;j<=n;++j){
//			dp[i][j]=max(dp[i][j-1],tmp)+a[j];
            dp[j]=max(dp[j-1],premax[j-1])+a[j];// premax[j-1]表示上一层前j-1的最大和 

            premax[j-1]=tmp;//更新premax数组,每次都等到dp[j]用完了premax[j-1]才更新
			                 //因为这么做才是之前即i-1层的premax[j-1];
			tmp=max(tmp,dp[j]);
			//新更新的premax[j-1]求法:
			//premax数组存的是上一层(i-1)的前j-1项最大dp值;
			//这里的更新是在本层dp用完premax数组后更新,
			//所以更新的值就是此时前j项的最大dp值 
		}
		
	}
	cout<<tmp<<endl;
}

int main(){
	while(cin>>m>>n){
	    memset(a,0,sizeof(a));
        memset(premax,0,sizeof(premax));
		for(int i=1;i<=n;i++){
			cin>>a[i];
		}
		memset(dp,0,sizeof(dp));
		solve();
	}
} 

 

三、THE END

滑动数组还是要花很长时间去理解,就像premax的使用一样,一维数组的更新是在什么时候,如何利用语句间的顺序来表示使用的顺序以来保证更新的顺序,感觉这一晚上没白用,还是会了90%以上,超级欢迎对这道题有疑问的你来评论,最近都在刷题,每刷一道写一篇博客用来巩固,所以经常在线
明天加油,今天晚安

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值