HDU1024 Max Sum Plus Plus 【区间dp】【滚动数组】

HDU1024 Max Sum Plus Plus

题意:给你一个N个元素的数列,你需要从中选M个区间,区间之间不能有交叉,问选取的M个区间之和最大值是多少? (N是1e6的数量级)

分析

我们考虑一个数一个数的放,过程是怎么样的。如果当前是选取第i个区间,现在要尝试放入a[j],那么就会出现两种情况:
1.a[j]直接跟在第i个区间的后面,最开始相当于跟在空区间的后面,后来就是a[j+1]跟在a[j]的后面组成区间
2.找到j之前选择i-1个区间的最优值+新开一个区间[j,j].

假如现在是第i轮区间选择:

dp[j]: 当前轮第j个位置的两种选择情况的最大值
mx:实时保存本轮在第j个位置选择后的最优值,当前轮的最优值
best[j-1]:上一轮在区间[1,j-1]选取i-1个区间的最优值,best[]是一个滚动数组,保存当前轮的最优值在下一轮使用

遇到的问题

找到j之前选择i-1个区间的最优值应该怎么处理呢?
当我们进行一轮新区间的时候,我们要使用到上一轮的j之前的最优值,同时又要保存j之前选取新区间之后的最优值
第一轮区间选择,其j之前的最优值都是0,因为只选取了0个区间
当我们用了上一轮的best[j-1],紧接着就要更新下一轮的best[j-1],此处具体看代码

AC代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 1e6+100;
typedef long long ll;
int M,N;
int arr[maxn];//原数组
ll best[maxn],dp[maxn];//best上一轮的最优值,本轮dp[j]:本轮选择了j位置的最优值
int main(){
    while(~scanf("%d %d",&M,&N)){
        memset(best,0,sizeof(ll)*N+10);
        memset(dp,0,sizeof(ll)*N+10);
        ll mx;
        for(int i = 1;i<=N;i++) scanf("%d",&arr[i]);
        for(int i = 1;i<=M;i++){//轮次
            mx = -1e18;
            for(int j = i;j<=N;j++){
                dp[j] = max(dp[j-1],best[j-1])+arr[j];//选择j位置后的最优值,使用掉上一轮best[j-1]
                best[j-1] = mx;//保存本轮的j-1的最优值,放在下一轮用
                mx = max(mx,dp[j]);//更新本轮j位置的最优值
            }
        }
        printf("%lld\n",mx);
    }

    return 0;
}
全部评论

相关推荐

05-09 14:45
门头沟学院 Java
点赞 评论 收藏
分享
家人们,我现在真的好纠结。我是26届的,目前还没有实习过。我现在的情况是,想参加秋招,但是感觉自己的简历特别空,没有实习经历会不会秋招直接凉凉啊?可我又听说现在很多公司对26届实习生也不太感冒,说什么不确定性大。而且我最近在准备考公,时间上也有点冲突。要是把时间花在实习上,备考时间就少了。但要是不实习,又怕以后就业有问题😫有没有懂行的友友帮我分析分析:26届现在不实习,秋招找工作真的会很难吗?考公和实习该怎么平衡啊?如果现在不实习,考完公再去找实习还来得及吗?真的太焦虑了,希望大家能给我点建议🙏
小破站_程序员YT:我可能和大家的观点不一样。人的精力是有限的,不能既要还要。你又想实习又想考公最后又要秋招上岸,我觉得哪有那么多的选择。你如果想考上岸,那就全力以赴。如果想秋招上岸,就继续投实习,投没了,就继续准备秋招,秋招不行继续春招。别到最后,考公没上岸,觉得是花了时间浪费在找实习上了, 秋招没上岸,觉得是浪费时间准备考公去了。我是认为很难说可以去平衡 不喜勿喷,可以叫我删除
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务