Max Sum Plus Plus HDU - 1024

29 篇文章 0 订阅

题目链接
题意:给你一个n,m,求序列长度为n的序列n中找到m个区间,要求m个区间和最少,求区间和的大小。
题解:我们分析题目,整体的数组长度为n,我们需要将数组中m个区间和加起来最大(区间不相交)。所以有两个状态,一是n,二是m,所以是二维的dp。我们可以将dp[i][j]表示为在前j个数中找,将j个数分解成i部分,且最后一个数是a[j],这样我们可以找到状态方程 dp[i][j]=max(dp[i][j-1]+a[j],dp[i-1][k]+a[j]) 其中dp[i-1][k]表示之前的长度的最大值。其中dp[i][j-1]表示j承接之前的数组,dp[i-1][k]表示找到之前的最大值然后另开辟一个区间,这样找是正确的。这样两维的情况下可能会爆内存,爆时间(三维的),所以我们应该要优化代码,这里我们可以优化的是dp[i-1][k]就是前面过程中的分成i-1段的最大值,所以我们动态的维护一个最大值即可。
下面是AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
int a[N],dp[N],maxx[N];
signed main()
{
    int n,m;
    while(~scanf("%d%d",&m,&n))
    {
        //memset(pre_max,0,sizeof(pre_max));
        //memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++) maxx[i]=0;
        for(int i=1;i<=n;i++) dp[i]=0;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        int mx;
        for(int i=1;i<=m;i++)//这里n,m两个维度的顺序是不能互换的,因为如果换了的话,正常的3维是可以的,但是优化的是不行的,因为额这样的话我就没办法保存前一段的最大值。
        {
            mx=-inf;
            for(int j=i;j<=n;j++)//这里只需要从i开始,因为分成i部分至少要i个数,这里空间优化类似于01背包,但并不是完全相同的,因为这里实际上是于背包不同的,背包实际上是两维的,这里实际上是三维的变成两维的了,直接优化了一维,所以在优化的时候一定要小心,在理解的前提下优化.
            {
                dp[j]=max(dp[j-1],maxx[j-1])+a[j];
                maxx[j-1]=mx;//这里是存取被分成i段时的最大值,方便进行i+1段时的dp
                mx=max(dp[j],mx);//这里取最大,保证之后的mx是最大的,这里其实初始化暗藏初始化,就是每次mx初始化为-inf就是为了将表示将i-1分成i-1段时是不可能的
            }
        }
        printf("%d\n",mx);
    }
    return 0;
}

总结:dp问题解答出来的关键一步就是分析状态,这里就是需要两个状态(n,m),然后对状态赋予恰当的定义(即状态表示),这样就可以正确的写出转移方程。而且在想状态表示的时候一定要从小想起,如果一开始就想普遍情况下的话,是很难想到的,而且在写dp的过程中不是知道转移方程后实际上是不需要还原过程的,dp的还原和递归类似,很难还原,因为他是一个动态的过程,所以我们没必要取还原过程,正确的表示状态后,写出转移方程后就能得到答案,dp的过程其实是实际过程的虚拟化,我们不必去还原过程

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值