最大子段和(DP)
哎哟,花了好久,终于把这玩意儿搞明白了......
以下就是我个人的看法了~
Warning:写这篇文章的是一个小渣渣!在大街上逛的时候请不要认错人!
插播一则广告
感谢百度百科
感谢知乎
感谢CSDN
感谢CNBLOGS
360去死吧
题面描述:
给定n个整数(可能为负数)
组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。
百度简略解释:
当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n 例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。
本人思路:
人家是要你求以a[i]+a[i+1]+...+a[j]的最大值对吧?
那好,我们打开 语文书 网页,看看动态规划的要求
1) 问题具有最优子结构性质。如果问题的最优解所包含的 子问题的解也是最优的,我们就称该问题具有最优子结 构性质。
2) 无后效性。当前的若干个状态值一旦确定,则此后过程的演变就只和这若干个状态的值有关。
(转自CSDN 其实好像没啥吧)
然后我们再打量打量这道题目
首先最优子结构
我们很容易就能看出,如果a[i]+a[i+1]+...+a[j]是最优解,
那么a[i]+a[i+1]+...+a[j-1](或者是a[i+1]+a[i+2]+...+a[j]之类)也一定会是最优的。
为什么呢
我们来分析一下:
假设a[1],a[2],a[3],a[4],a[5]赋值为-1,5,6,-3,-50
那么我们可知最大子段是5,6
即a[2]+a[3],这是在数的个数为2的时候的最优解
同样的,我们也能够看出,整个序列中数的个数为1的情况下,最大子段是6
这样就能够简单地证明该题的最优子结构。
然后是无后效性
这个也很简单的好吧
你求了这个会影响其他的吗?
真的* * * * * * * * * * * *啊这个问题
百度的代码如下
1 #include <stdlib.h> 2 #include<stdio.h> 3 int main() 4 { 5 int count; 6 int a[100]; 7 int b[100]; 8 int i; 9 int max; 10 scanf("%d",&count); 11 for(i=0; i<count; i++) 12 { 13 scanf("%d",&a[i]); 14 } 15 b[0]=a[0]; 16 max=b[0]; 17 for(i=1; i<count; i++) 18 { 19 if(b[i-1]>0) 20 b[i]=b[i-1]+a[i]; 21 else 22 b[i]=a[i]; 23 if(b[i]>max) 24 max=b[i]; 25 } 26 printf("%d\n",max); 27 return 0; 28 }
其实百度的语言只是生硬晦涩了一点而已呢
本人思路:
Warning:最佳食用方式:蘸着上面的百度代码吃!
首先,这道题目是在讲DP嘛
那我们先推一推状态转移方程(考场上可不能这样!)
先翻到上面,看到了没,
最优子结构!
因此我们可以推出状态转移方程:(数组名称均来自蘸酱的代码)
b[j]=max(b[j-1]+a[i],a[j]);
对啦
要我解释一下吗(总觉得自己好啰嗦啊)
这个状态转移方程的意思就是:判断以第i个元素开头,第j个元素结尾的子段,能不能加上一个新的元素,使得新的子段比原先的子段还大
我的代码就不放出来啦!(都差不多啊对不对啊差不多差不多啊啊啊)
最后把百科放出来,不喜欢这篇blog的童鞋们可以自行查阅~
(突然发现百科里的分治法好像有点问题...还好没抄哈哈哈哈哈哈哈哈哈哈哈哈)
503 ERROR!
502 ERROR!
504 ERROR!
BOOM!
The End