hdoj1024 Max Sum Plus Plus (DP)
来源:互联网 发布:yum install gcc 失败 编辑:程序博客网 时间:2024/06/08 08:02
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1024
题意:
给一个数字序列a1,a2,a3,...,an,(n<=1000000),求从中取出m个子序列的最大和,单个子序列必须是连续的,而且各个子序列之间没有重叠部分;
输入格式为:m n a1 a2 a3 ... an
思路:
dp[m][n]=max( dp[m][n-1]+s[n] ,dp[m-1][t]+s[n]),其中m-1<=t<=n-1;dp[m][n]表示前n列数据中选m个子段的最大和,第n列一定要包含在序列中,(原因很简单,如果不包含在其中,那么就会出现dp[m][n]=dp[m][x],x<n;也就是说数据是重复的,而且状态转移方程也会发生变化,不再是上述方程)dp[m][n-1]+s[n]表示前n-1列中取m个子段,s[n-1]是在第m段中的,s[n]放入第m段即可;dp[m-1][t]+s[n]表示将s[n]单独做为第m段,因此还要在前面的序列中找m-1个子段,而这m-1个子段可能是dp[m-1][t]中的任意一个(m-1<=t<=n-1);s[n]存输入的序列,sum[n]表示前n项和,由于在求dp[m][n]时要用到 max(dp[m-1][m-1],...,dp[m-1][n-1]),也就是dp[m-1][t]中的最大值,因此用dp_low[n-1]来存取m-1到n-1列中取m-1子段的最大值,而dp_high[n]就存取n列中取m子段的最大值;由于每次求dp[m][n]时都要用到它的前一个状态dp[m-1][n-1];于是先从它的初始状态着手:
当m=1时,基本状态方程为dp[j]=max(dp[j-1],0)+s[j],(dp[0]=0,1<=j<=n);依此得到dp_high[j]=max(dp_high[j-1],0)+s[j],(dp_high[0]=0,1<=j<=n),dp_low[j]=max( dp_high[j],dp_low[j-1] ),(dp_low[0]=INI_MIN);只要得到了初始的dp_low[],求dp_high[]就容易了。
当m>1时,前j列中取i个子段,当i==j时,dp_high[j]=sum[j];当j>i时,dp_high[j]=max(dp_high[j-1],dp_low[j-1])+s[j],dp_high[j-1]表示j-1列取i个子段的最大值,dp_low[j-1]表示i-1到j-1列取i-1个子段的最大值,算出dp_high[j]的值后需要立即更dp_low[j-1]的值为取i个子段,以供取i+1个子段时dp_high[j]使用,dp_low[j-1]=max(dp_high[j-1],dp_low[j-2]),要考虑j的临界取值情况。当求出dp_high[n]时,只需要更新到dp_low[n-1],也就是用不到dp_low[n],这里仍然要算出db_low[n]来存放i到n列选i个子段时的最大值,最后选m子段的结果就存放在db_low[n]中。
#include <stdio.h>int s[1000009];int dp_high[1000009];int dp_low[1000009];int sum[1000009];int max(int a,int b){if(a>b)return a;else return b;}int main(){int m,n,i,j;sum[0]=0;while(scanf("%d %d",&m,&n)!=EOF){memset(dp_high,0,sizeof(dp_high));memset(dp_low,0,sizeof(dp_low));dp_low[0]=-100000000;for(i=1;i<=n;i++){scanf("%d",&s[i]);sum[i]=sum[i-1]+s[i];dp_high[i]=max(dp_high[i-1],0)+s[i];dp_low[i]=max(dp_high[i],dp_low[i-1]);}for(i=2;i<=m;i++){dp_high[i]=sum[i];for(j=i+1;j<=n;j++){dp_high[j]=max(dp_high[j-1],dp_low[j-1])+s[j];if(j==i+1){dp_low[j-1]=dp_high[j-1];}else{dp_low[j-1]=max(dp_high[j-1],dp_low[j-2]);}}if(j==i+1){dp_low[j-1]=dp_high[j-1];}else{dp_low[j-1]=max(dp_high[j-1],dp_low[j-2]);}}printf("%d\n",dp_low[n]);}return 0;}
代码优化:
#include <stdio.h>int s[1000009];int dp[1000009];int sum[1000009];int t_max[1000009];int max(int a,int b){return a>b?a:b;}int main(){int m,n,i,j;while(scanf("%d %d",&m,&n)!=EOF){memset(dp,0,sizeof(dp));memset(t_max,0,sizeof(t_max));sum[0]=0;for(i=1;i<=n;i++){scanf("%d",&s[i]);sum[i]=sum[i-1]+s[i];}for(i=1;i<=m;i++){dp[i]=sum[i];t_max[i-1]=-1000000000; //后面代码中t_max[j-2]有时表示前x列取x+1个子段,这里赋极小值做特殊数据处理for(j=i+1;j<=n;j++){dp[j]=max(dp[j-1],t_max[j-1])+s[j];//t_max[j-1]为i-1到j-1列取i-1个子段最大值t_max[j-1]=max(dp[j-1],t_max[j-2]); //t_max[j-1]为i-1到j-1列取i个子段最大值}t_max[j-1]=max(dp[j-1],t_max[j-2]); //此处j-1==n,可理解为前i-1到n列取i个子段最大值}printf("%d\n",t_max[n]);}return 0;}
- hdoj1024 Max Sum Plus Plus(DP!DP!)
- HDOJ1024 max sum plus plus(DP)
- hdoj1024 Max Sum Plus Plus (DP)
- HDOJ1024 Max Sum Plus Plus(区间DP)
- Max Sum Plus Plus----DP
- hdu1244 Max Sum Plus Plus Plus--DP
- hdu 1024 Max Sum Plus Plus--DP
- hdu 1024 Max Sum Plus Plus(dp)
- hdu-1024-Max Sum Plus Plus-DP
- hdu 1024 Max Sum Plus Plus(dp)
- hdu 1024 Max Sum Plus Plus dp
- HDU1024 Max Sum Plus Plus 【DP】
- HDU1024 Max Sum Plus Plus(DP)
- Hdoj 1024 Max Sum Plus Plus 【DP】
- hdu1024--Max Sum Plus Plus(dp)
- HDU DP - 1024 Max Sum Plus Plus
- HDU 1024 Max Sum Plus Plus【DP】
- Max Sum Plus Plus(基础dp)
- 大数据架构和模式(五)对大数据问题应用解决方案模式并选择实现它的产品
- 第二章 逻辑代数基础
- POJ2378【树形DP】
- 程序员日常工作英文20170523
- ubuntu14.04安装CPU版SSD(Single Shot MultiBox Detector)/Caffe版本
- hdoj1024 Max Sum Plus Plus (DP)
- Fruit Ninja II(山东省第三届ACM大学生程序设计竞赛 )
- 初始三层
- matlab中对矩阵进行排序
- markdown编辑器使用方法
- 机器学习教程之4-正则化(Regularization)
- Linux下系统时间函数--->gettimeofday
- jquery.min.js:2 Uncaught RangeError: Maximum call stack size exceeded
- Kotlin笔记(一)简介