最大子段和(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
",max);
27     return 0;
28 }
百度

 其实百度的语言只是生硬晦涩了一点而已呢


本人思路:

Warning:最佳食用方式:蘸着上面的百度代码吃!

首先,这道题目是在讲DP嘛

那我们先推一推状态转移方程(考场上可不能这样!

先翻到上面,看到了没,

最优子结构!

因此我们可以推出状态转移方程:(数组名称均来自蘸酱的代码

b[j]=max(b[j-1]+a[i],a[j]);

对啦

要我解释一下吗(总觉得自己好啰嗦啊

这个状态转移方程的意思就是:判断以第i个元素开头,第j个元素结尾的子段,能不能加上一个新的元素,使得新的子段比原先的子段还大

我的代码就不放出来啦!(都差不多啊对不对啊差不多差不多啊啊啊)


最后把百科放出来,不喜欢这篇blog的童鞋们可以自行查阅~

Baike

(突然发现百科里的分治法好像有点问题...还好没抄哈哈哈哈哈哈哈哈哈哈哈哈


 

 

503 ERROR!

502 ERROR!

504 ERROR!

BOOM!

The End

原文地址:https://www.cnblogs.com/Fraction/p/ZuiDaZiDuanHe.html