首先呢,先谢谢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被改变呢?
将前两种方程结和起来就好了