hdu 1024(dp*优化)

来源:互联网 发布:ubuntu tmux 编辑:程序博客网 时间:2024/05/16 09:19
本题的大致意思为给定一个数组,求其分成m个不相交子段和最大值的问题。

设Num为给定数组,n为数组中的元素总数,Status[i][j]表示前i个数在选取第i个数的前提下分成j段的最大值,其中1<=j<=i<=n && j<=m,状态转移方程为:

Status[i][j]=Max(Status[i-1][j]+Num[i],Max(Status[0][j-1]~Status[i-1][j-1])+Num[i])

乍看一下这个方程挺吓人的,因为题中n的限定范围为1~1,000,000而m得限定范围没有给出,m只要稍微大一点就会爆内存。但仔细分析后就会发现Status[i][j]的求解只和Status[*][j]与Status[*][j-1]有关所以本题只需要两个一维数组即可搞定状态转移。

在进行更进一步的分析还会发现其实Max(Status[0][j-1]~Status[i-1][j-1])根本不需要单独求取。在求取now_Status(保存本次状态的数组)的过程中即可对pre_Status(保存前一次状态的数组)进行同步更新。

#include <iostream>#include<stdio.h>#include<string.h>using namespace std;#define N 1000005#define inf 0x3f3f3f3fint max(int a,int b){return a>b?a:b;}int n,m,maxnn;int f[N],dp[N],maxn[N];int main(int argc, char *argv[]) {while(~scanf("%d%d",&m,&n)){for(int i=1;i<=n;i++){scanf("%d",&f[i]);dp[i]=0;maxn[i]=0;}for(int j=1;j<=m;j++){        maxnn=-inf;for(int i=j;i<=n;i++){/*for(int k=j-1;k<=i-1;k++)/////超时 maxn=max(maxn,dp2[k]+f[i]);dp2[i]=dp[i];*/dp[i]=max(dp[i-1]+f[i],maxn[i-1]+f[i]);maxn[i-1]=maxnn;//////////优化 maxnn=max(maxnn,dp[i]);/////////}}printf("%d\n",maxnn);}return 0;}


0 0
原创粉丝点击