首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【HDU】1024 - Max Sum Plus Plus(dp优化)

【HDU】1024 - Max Sum Plus Plus(dp优化)

作者头像
FishWang
发布2025-08-27 09:48:17
发布2025-08-27 09:48:17
16700
代码可运行
举报
运行总次数:0
代码可运行

点击打开题目

Max Sum Plus Plus

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 25325 Accepted Submission(s): 8738

Problem Description

Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you are faced with a more difficult problem. Given a consecutive number sequence S 1, S 2, S 3, S 4 ... S x, ... S n (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ S x ≤ 32767). We define a function sum(i, j) = S i + ... + S j (1 ≤ i ≤ j ≤ n). Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i 1, j 1) + sum(i 2, j 2) + sum(i 3, j 3) + ... + sum(i m, j m) maximal (i x ≤ i y ≤ j x or i x ≤ j y ≤ j x is not allowed). But I`m lazy, I don't want to write a special-judge module, so you don't have to output m pairs of i and j, just output the maximal summation of sum(i x, j x)(1 ≤ x ≤ m) instead. ^_^

Input

Each test case will begin with two integers m and n, followed by n integers S 1, S 2, S 3 ... S n. Process to the end of file.

Output

Output the maximal summation described above in one line.

Sample Input

代码语言:javascript
代码运行次数:0
运行
复制
   1 3 1 2 3
2 6 -1 4 -2 3 -2 3

Sample Output

代码语言:javascript
代码运行次数:0
运行
复制
   6
8


   
    
     Hint
    
Huge input, scanf and dynamic programming is recommended.

Author

JGShining(极光炫影)

一道卡了很久的题,从今天开始专门拆dp,所以先拿出来开刀了。

首先用初步的思路,建立一个dp[i][j] 的二维数组,i表示有i个子段,j表示以num[j]为结尾。那么:

dp[ i ][ j ] = max (dp[ i-1 ][ t ] , dp[ i ][ j-1 ]) + num[ j ] 这里要特别注意那是t,范围是:1 <= t <= j-1 ,表示 i-1 个子段时前面数所能构成的最大sum。

如果按这个思路实现的话,我们需要3个for循环,而题目给出的n又非常大,所以我们不能这样直接去算( 就算不考虑时间的问题,dp数组都开不开啊!)

然后我参考了:点击打开链接 的思路。

首先是时间上的优化:

计算dp[ i-1 ][ t ] 的时候是浪费了不少时间,但是追根揭底这一步只是要 i-1 个子段时 1 ~ j-1个数中所能构成的最大和,这个值在我们算dp[ i-1 ] [ j-1 ]的时候其实可以得出来,所以我们再开一个数组(我这里命名为maxx[ j ],原文章不是),这个数组的含义是 i-1 个子段时,前面的数可以构成的最大和(就是dp[ i-1 ][ t ])。

然后我们来考虑赋值的问题,maxx [ j ] 应该等于 dp[ i ] [ j ],但是我们并不能直接赋值,因为计算dp[ i ] [ j+1 ] 的时候,还需要用到maxx [ j ] 原来的值,如果冒然赋值则会覆盖掉原来的值。所以我们先把这个(dp[ i ][ j ])值存到maxx[ n ]上面,当dp[ i ] [ j + 1 ]的时候才赋值就行啦。

然后是空间上的优化:

因为dp数组的两个维度的数值会很大,这个数组也不能使用,我们观察一下,dp数组在递推的过程中,dp[ i - 1][ t ]这个值我们已经用maxx数组很好的解决了,只剩一个dp[ i ] [ j - 1] 的值我们需要用到,那么我们只需要找一个整形变量 t 存一下这个值就行了。

代码如下:(建议先理解思路再打)

代码语言:javascript
代码运行次数:0
运行
复制
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MAX 1000000
int n,m;
int num[MAX+11];
int maxx[MAX+11];		//i-1 个子段的最大值 
int t;		//暂时记录 dp[i][j] 的值 
int main()
{
	while (~scanf ("%d %d",&m,&n))
	{
		for (int i = 1 ; i <= n ; i++)
			scanf ("%d",&num[i]);
		CLR(maxx,0);
		for (int i = 1 ; i <= m ; i++)
		{
			t = 0;
			for (int j = 1 ; j <= i ; j++)		//有i个子段,最少从i+1开始计算 
				t += num[j];
			maxx[n] = t;
			for (int j = i + 1 ; j <= n ; j++)
			{
				t = max (maxx[j-1] + num[j] , t + num[j]);
				maxx[j-1] = maxx[n];
				maxx[n] = max(maxx[n] , t);
			}
		}
		printf ("%d\n",maxx[n]);
	}
	return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Max Sum Plus Plus
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档