最大子段和
来源:互联网 发布:有淘宝账号就能贷款 编辑:程序博客网 时间:2024/06/05 10:13
动态规划是一个很巧妙的算法,但是能够想得到如何用动态规划,我感觉还是有难度的。不过慢慢来,先从小的动态规划的例子开始。
现在有一个数组,请找出这个数组的最大子段和。(即 max (a[i]+a[i+1]+...+a[j]) 0<=i<=j<=n-1)
现在我们的思路是: 记s[i]为 a[0]到a[i]中包含a[i](即以a[i]为结尾)的最大子段和,则s[i]如何用s[i-1]来表示?
s[i] = s[i-1] + a[i]; s[i-1]>=0 或者
s[i] = a[i]; s[i-1]<0
所以根据s[i-1]来计算s[i]时会遇到这两种情况。计算s[i]时只用到s[i-1]和a[i], 所以我们可以只保留s[i-1]的值,对于s[i-2]及以前的值可以不保存。
在s[i]中找最大的,就是我们的结果了。
那究竟哪一段是最大的呢。这个方法不唯一。比如,你可以用数组记录每一个s[i],那如果s[i] = a[i]的时候,说明a[i-1]不在s[i]的计算结果中,a[i-1]就没被选择。
现在我们用一个辅助数组P来记录一下, p[i] = 1 表示 在计算s[i]时 包含了 p[i-1]; p[i] = 0 表示 p[i-1]没有被包含。这样我们就可以找到哪一个子段了。看一下下面的代码吧
- /**
- * 动态规划:计算最大子段和
- * 算法描述:
- * 数组a 有n个元素, 记 s[i] 为从a【0】到a[i]中,包含a[i]的最大子段和
- * 则: s[i] 的值为: s[i-1]>0时, s[i-1]+a[i]
- * 否则 a[i]
- */
- #include <stdio.h>
- int maxSub(int *a, int n)
- {
- int i=0, max=0, max_pos = 0;
- int si_1=0, si = 0;//分别记录s[i-1], 和 s[i]的值
- int *p = (int *)malloc(n*sizeof(int)); //p[i] 助于记录哪些单元被选择, p[i]=1 表示s[i]计算的结果中中使用了s[i-1]的值
- if (p==NULL)
- return -1;
- max = si_1 = a[0];
- p[0] = 0;
- for (i=1; i<n; i++){
- if (si_1<0){
- p[i] = 0;
- si = a[i];
- } else{
- p[i] = 1;
- si = si_1+a[i];
- }
- si_1 = si;
- if (si>max){
- max = si;
- max_pos = i;
- }
- }
- //找到最大子段和的位置
- for (i=max_pos; i>=0; i--)
- if (p[i]==0)
- break;
- //即i..max_pos为最大子段和的元素
- printf("%d--%d:%d\n", i, max_pos, max);
- free(p);
- p = NULL;
- return max;
- }
- int main()
- {
- int n = 10;
- int a[10] = {3, 5, 6, 10, -2, -5, 3, 5, -112, -324};
- maxSub(a, n);
- return 0;
- }
0 0
- 最大子段和
- 最大子段和
- 最大子段和
- 最大子段和
- “最大子段和”
- 最大子段和
- 最大子段和
- 最大子段和
- 最大子段和
- 最大子段和
- 最大子段和
- 最大子段和
- 最大子段和
- 最大子段和
- 最大子段和
- 最大子段和
- 最大子段和
- 最大子段和
- mysql安装
- Go语言linux下构造tcp数据包(不使用net包和Cgo)
- 构造螺旋矩阵
- Linux用户组添加查看
- Ubuntu13.04 “Language support” icon missing in System Settings
- 最大子段和
- 每天一个linux命令(47):iostat命令
- 数据建模基础理论 – 数据建模及规范化(1)
- XManager4基于gdm连接centos6.4图形界面(绝对可用)
- 控件使用
- 放大的X
- android获取手机应用之后放入gridview之后的点击事件
- Servlet
- 火狐和IE的window.event对象详解