标签:
实在是太颓废了,所以开始写点东西吧。。。。
最大子段和: 给定N个数(可能为负整数)组成的序列a1...an,求该序列形如∑ak(i<=k<=j)的子段和的最大值。当所有整数均为负整数时定义其最大的子段和为0.
依据题意我们可以确定 最优值为max(0,max∑ak(i<=i<=j<=n)); 若我们令b[j] = max∑ak(1<=i<=j)是从序列a的第i个数到第j个数的最大和,那么我们最后的答案就是找出b数组里面记录的最大的那个值就是答案。由b[j]的定义可以知道b[j-1]>0时,b[j] = b[j-1]+a[j]否则b[j] = a[j];由此得出递推式b[j] = max(b[j-1]+a[j],a[j]) (1<=j<=n)
代码如下
1 int Maxsum1(int n,int *a) 2 { 3 int sum = 0,b = 0; 4 for(int i=1;i<=n;i++){ 5 if(b>0) b += a[i]; 6 else b = a[i]; 7 if(b > sum ) sum = b; 8 } 9 return sum; 10 }
最大子段和的推广
(1)最大子矩阵:给定一个m行n列的整数矩阵A,求其元素和最大的子矩阵
很明显最大子矩阵和的问题是最大子段和的问题向二维的推广,我们用数组a[1:m][1:n]表示给定的矩阵A 其子数组a[i1:i2][j1:j2]表示左上角和右下角的行列坐标分别为(i1,j1)(i2,j2)的子矩阵 其个各个元素之和 记为 S(i1,i2,j1,j2)= ∑∑a[i][j] (i1<=i<=i2,j1<=j<=j2) 那么ans = Max S(i1,i2,j1,j2) (1<=i1<=i2<=m,1<=j1<=j2<=n)
我们可以令t(i1,i2) = maxS(i1,i2,j1,j2)(i<=j1<=j2<=n) = Max∑∑a[i][j] 同样我们令b[j] = ∑a[i][j](i1<=i<=i2) 于是 t(i1,i2) = max∑b[j](1<=j1<=j2<=n) 这又回到了一维的情况于是我们可以得到如下代码
1 int Maxsum2(int m,int n,int a[105][105] ) 2 { 3 int sum = 0; 4 int b[105]; 5 for(int i=1;i<=m;i++){ 6 memset(b,0,sizeof(b)); 7 for(int j=i;j<=m;j++){ 8 for(int k=1;k<=n;k++) b[k] += a[j][k]; 9 int Max = Maxsum1(n,b); 10 if(Max > sum) sum = Max; 11 } 12 } 13 return sum ; 14 }
最大子矩阵在poj上面有原题目 题号是1050 代码如下
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int M = 105; int a[M][M]; int Maxsum1(int n,int *a) { int sum = 0,b = 0; for(int i=1;i<=n;i++){ if(b>0) b += a[i]; else b = a[i]; if(b > sum ) sum = b; } return sum; } int Maxsum2(int m,int n,int a[105][105] ) { int sum = 0; int b[105]; for(int i=1;i<=m;i++){ memset(b,0,sizeof(b)); for(int j=i;j<=m;j++){ for(int k=1;k<=n;k++) b[k] += a[j][k]; int Max = Maxsum1(n,b); if(Max > sum) sum = Max; } } return sum ; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++) scanf("%d",&a[i][j]); } printf("%d\n",Maxsum2(n,n,a)); return 0; }
标签:
原文地址:http://www.cnblogs.com/lmlyzxiao/p/4640901.html