最大子段和的拓展

首先呢,先谢谢zhw老师。。

最大字段和 即给出n个数,找出一段连续的区间,使得其和最大

这题太老套了,直接写代码吧

for(int i=1;i<=n;i++)
f[i]=max(f[i-1],0)+a[i];
for(int i=1;i<=n;i++)
ans=max(ans,f[i]);


接下来就有一个问题:给定一个n*n的矩阵,找一个子矩阵使得这个子矩阵中元素和最大。输出这个最大和    n<=200

显然枚举两个坐标会超时。

枚举子矩阵所在的上下两列,求出每行之间的数字和,则变成了一维的最大字段和问题,可以O(n)解决

用前缀和预处理出每一行的和即可

这就是最大子段和在二维矩阵中应用的一个方面


接着再看一个新问题

给定n个数,将其中一个数改成常数P,求最大子段和 n<=1000000

其实和一维最大子段和一样,可以用DP解决

再多加一个状态,f[i][0/1]表示前i个数中是否有数改变

则:

f[i][1]=max{f[i-1][1]+a[i],p,f[i-1][0]+p};

f[i][0]=max{f[i-1][0]+a[i],a[i]};

答案为max{f[i][1]}


将其上升到二维,做法也是如此。枚举答案所在的上行与下行,对其内的每一列压成一个数,转化为一维问题

注意:由于只改变一个数,所以贪心寻找P,即该列最小的数,预处理(二维滑动窗口)

总复杂度:O(n^3)



接下来,最大m段和

设f[i][j]表示在前i个数字中取了j段,且包含a[i]

则有f[i][j]=max{f[i-1][j]+a[i],f[i-1][j-1]+a[i]};j<=k<=i-1

答案:max{f[i][m]};


二维亦是如此


那如果再有一个数p被改变呢?

将前两种方程结和起来就好了


你可能感兴趣的:(动态规划)