子矩阵最大累加和——算法笔记

子矩阵最大累加和——算法笔记_第1张图片

假定只有一行,那就和求最大和子数组一样
如果限定两行,可以把两行按列求和,同上
所以我们以第一行当做起点,依次累加后面的每一行后,都求一个最大子数组和
以第二行作为起点,依次累加后面的每一行后,都求一个最大子数组和
每次求出来的和与历史最大值比较,如果更大,则更新
N^3时间复杂度

#include 
#include 

using namespace std;

#define MAX 10

int sums[MAX];//按列求和

int maxSum(int matrix[MAX][MAX], int M, int N)		//M行 N列 
{
	int findByDp(int *arr,int len);
    int beginRow = 0;//以它为起始行
    int max = 0;//历史最大的子矩阵和
    while(beginRow < M)   //起始行
    {
        for(int i = beginRow; i < M; i++)   //从起始行到第i行
        {
            //按列累加
            for(int j = 0; j < N; j++)
            {
                sums[j] += matrix[i][j];
            }
            //  累加完成
            //  求出sums的最大和子数组O(n)
            int t = findByDp(sums, N);
            if(t > max)
                max = t;
        }
        //另起一行作为起始行.把sums清零
        memset(sums, 0, sizeof(sums));//快速地将sums的每个元素都设定为0
        beginRow++;
    }
    return max;
}

int findByDp(int *arr,int len)		//用递推写 
{
	int sumj = arr[0];
	int max = sumj;
	int left=0, right=0;
	
	for(int j=1; j<len; j++)
	{
		if(sumj>=0)		//左子表的最大和为正,继续向后累加 
		{
			sumj += arr[j];	
		}
		else
		{
			sumj = arr[j];
			left = j;		//丢弃前部分和的同时,更新left 
		}
		
		if(sumj > max)
		{
			max = sumj;
			right = j;
		}
	}
	return max;
	
	
}

 
int main()
{
    int A[MAX][MAX];
    memset(A, 0, sizeof(A));
    int r,c;
    cin >> r >> c;
    int i, j;
    for(i = 0; i < r; i++)
    {
        for(j=0; j <c; j++)
        {
        	cin >> A[i][j];
		}
        
    }
    cout << maxSum(A, r, c);
}

你可能感兴趣的:(C++算法笔记)