hdu 1024 max sum plus plus
2015-10-30 10:44
381 查看
刚写这题时知道是dp但动态转移方程推不出来,后来上网上搜了题解。
先把问题简化,假如就选一段,这就是个经典的max sum dp。
状态转移方程为dp[i]=dp[i-1]+a[i]>a[i]?:dp[i-1]+a[i]:a[i];
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1003
再说这道题http://acm.hdu.edu.cn/showproblem.php?pid=1024;
题意是求不相交且连续的多个子列和的最大值。由一段找最大然后可以想到开一个二维数组dp[i][j];每个状态可理解为分为i段时第j个元素选入时的最大值,所以要么选第j个数时在上一层的基础上从新将第j个数开为一段,要么在本层的基础上加上第j个数,又应为是要最优,自然就要最大,所以得状态转移方程dp[i][j]=max(dp[i][j-1]+a[j],max(dp[i-1][k])+a[j](i-1<=k<j));
由于给的范围很大<=1000000;开2维的数组爆内存,所以是否一维的可以,我一开始想时是开两个数组交替,反正只和本层和上层有关,但太麻烦,要交替赋值,时间耗费大。
没次的更新需要用到上一层的到i-1~j-1为止的最大值,所以可以开个数组记录;方程就变成dp[j]=max(dp[j-1]+a[j],pre[j]+a[j]);
最后找dp
~dp[p]的最大就行了,n为要分的段,p为元素总个数。
下面看两段代码:
先把问题简化,假如就选一段,这就是个经典的max sum dp。
状态转移方程为dp[i]=dp[i-1]+a[i]>a[i]?:dp[i-1]+a[i]:a[i];
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1003
再说这道题http://acm.hdu.edu.cn/showproblem.php?pid=1024;
题意是求不相交且连续的多个子列和的最大值。由一段找最大然后可以想到开一个二维数组dp[i][j];每个状态可理解为分为i段时第j个元素选入时的最大值,所以要么选第j个数时在上一层的基础上从新将第j个数开为一段,要么在本层的基础上加上第j个数,又应为是要最优,自然就要最大,所以得状态转移方程dp[i][j]=max(dp[i][j-1]+a[j],max(dp[i-1][k])+a[j](i-1<=k<j));
由于给的范围很大<=1000000;开2维的数组爆内存,所以是否一维的可以,我一开始想时是开两个数组交替,反正只和本层和上层有关,但太麻烦,要交替赋值,时间耗费大。
没次的更新需要用到上一层的到i-1~j-1为止的最大值,所以可以开个数组记录;方程就变成dp[j]=max(dp[j-1]+a[j],pre[j]+a[j]);
最后找dp
~dp[p]的最大就行了,n为要分的段,p为元素总个数。
下面看两段代码:
#include<stdio.h> #include<algorithm> #include<iostream> #include<string.h> #include<stdlib.h> #include<math.h> using namespace std; typedef long long ll; ll a[1000005]; ll aa[1000005];//dp数组 ll b[1000005];//记录i-1~j-1的最大值数组 //ll pp[1000005]; int main(void) { ll i,j,k,p,q,l,n,m; while(scanf("%lld",&m)!=EOF) { scanf("%lld",&p); if(m>p)//m不可能超过p { m=p; } for(i=1; i<=p; i++) { scanf("%lld",&a[i]); } aa[0]=0; memset(b,0,sizeof(b));//每一次b都要初始化 for(i=1; i<=m; i++) { for(j=i; j<=p; j++) { aa[j]=aa[j-1]+a[j]>b[j]+a[j]?aa[j-1]+a[j]:b[j]+a[j]; } b[i]=aa[i];//本层循环完后更新b数组每次更新要从第i个数开始因为要分成i+1段就必须从能分成i段时加一个数,而分i段必须要i个数。 for(j=i+1; j<=p; j++) { b[j]=aa[j-1]>b[j-1]?aa[j-1]:b[j-1]; } } ll maxx=aa[m]; for(i=m; i<=p; i++) { if(maxx<aa[i]) { maxx=aa[i]; } } printf("%lld\n",maxx); } return 0; }
#include<stdio.h> #include<algorithm> #include<iostream> #include<string.h> #include<stdlib.h> #include<math.h> using namespace std; typedef long long ll; ll a[1000005]; ll aa[1000005]; ll b[1000005]; //ll pp[1000005]; int main(void) { ll i,j,k,p,q,l,n,m; while(scanf("%lld",&m)!=EOF) { scanf("%lld",&p); if(m>p) { m=p; } for(i=1; i<=p; i++) { scanf("%lld",&a[i]); } aa[0]=0; memset(b,0,sizeof(b)); for(i=1; i<=m; i++) { for(j=i; j<=p; j++) { aa[j]=aa[j-1]+a[j]>b[j]+a[j]?aa[j-1]+a[j]:b[j]+a[j]; if(j==i) { b[j]=aa[i]; } else { b[j]=aa[j-1]>b[j-1]?aa[j-1]:b[j-1];//此处优化了一下b的更新直接和aa的更新合并并不要在开一重,提高了代码的效率。 //因为当前是更新aa[j]所以b[j]记录的是i-1到j-1的最大更新完aa后再更新b并不影响aa[j+1]的更新b[j+1]还是上一层的更新完才变本层的。 } } } ll maxx=aa[m]; for(i=m; i<=p; i++) { if(maxx<aa[i]) { maxx=aa[i]; } } printf("%lld\n",maxx); } return 0; }
相关文章推荐
- SublimeText3 生成html标签快捷键
- 2015年影响谷歌搜索引擎排名的因素调查【完整版】
- Javascript模块化编程 1 :模块的写法
- Android M 新的运行时权限开发者需要知道的一切
- 整理 iOS 9 适配中出现的坑(图文)
- python第二章更多控制流程语句
- Daily Scrum 10.30
- cisco 2960交换机密码恢复教程
- Ubuntu 出现 grub rescue> 修复
- c/c++层log打印
- Java中Map的用法
- // 定位光标位置
- [Android knowledge]
- 一致性哈希算法与java实现
- centos7开机启动详解
- 数据结构——广义表和十字链表
- 浅谈XML 解析技术性能对比分析之 解析XML
- TreeMap 排序
- Android MVP模式
- static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store); 的作用