动态规划 求最大子矩阵和 合工大 程序设计艺术实验

3.输入一个矩阵,计算所有子矩阵中和的最大值.
例如,输入
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
输出为:15

为了做这个题目 我们首先要明白如何求最大子段的和,
例如
我给出数组的七个数字: 3,-2,1,-10,5,-1,2
3,-2,1 是一个子段 它的和为2
5,-1,2也是一个子段它的和为6
那我们如何只遍历一遍就能求出最大的子段和呢?下面我们将这个例子用手工的方法说明算法
我们这里定义sum为当前求得的最大子段和,tmp为保存当前正在求的子段.
刚开始我们让sum很小.从第一个数字开始遍历
tmp = 3, 这时tmp > sum,所以更新sum = tmp = 3;
接着我们再让tmp = tmp - 2 = 1, tmp < sum,所以继续下一轮循环.
tmp = tmp + 1 = 2, tmp < sum 进入下一轮
tmp = tmp -10 = -8 < 0 ,tmp < sum 进入下一轮
在这一轮中 我们发现,当前子段和 tmp < 0 了,这时无论下一个数字是正还是负,我们都舍去当前的子段和tmp,所以 tmp = 5,因为如果这时tmp += 5,相当于在原来负数的基础上加一个数,不如舍弃开始的负数.此时sum < tmp, sum = tmp = 5;进入下一轮循环
tmp += -1 = 4 ,tmp <sum 下一轮
tmp += 2 = 6 tmp > sum ,所以 sum = tmp = 6;

看懂了吗?

下面我们给出求最大子段和的代码:

#include <iostream>
using namespace std;

int main()
{
    
    
    int a[] = {
    
    5, -1, 4, -90, 32, -1, 3};
    int sum = -999;
    int i = 0;
    int b = 0;

    while(i < 7){
    
    

        if(b >= 0)
            b += a[i];
        else
            b = a[i];

        if(b > sum)
            sum = b;

        i++;
    }

    cout << sum;

    return 0;
}

那么求矩阵最大子矩阵和其实就是将其转化为求最大子段和,请您一定要看懂上方代码!

例如求下方矩阵的最大子矩阵和变为15 我们现在要思考的问题便是如何将其变为求最大子段和!
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
请宁仔细观察这两副图,有没有恍然大悟?

我们可以把第i行 到第j行的每一列的对应元素和储存在b数组里,然后再对b数组求最大子段即可,当然i是要从0行到n行,j从第i行到第n行,两个for循环控制就可,内层第三个for循环用来进行求最大子段.
下面便是代码

#include <iostream>
#include <cstring>
using namespace std;

int main()
{
    
    
    int a, b;
    cout << "请输入矩阵的行数和列数:" << endl;
    cin >> a >> b;
    int d[a][b];
    for(int i = 0; i < a; i++){
    
    
        for(int j = 0; j < b; j++){
    
    
            cin >> d[i][j];
        }
    }
    int sum, tmp;
    int c[b];
    sum = -999;
    for(int i = 0; i < a; i++){
    
    
        memset(c, 0 ,sizeof(c));
        for(int j = i; j < a; j++){
    
    
            tmp = 0;
            for(int k = 0; k < b; k++){
    
    
                c[k] += d[j][k];
                if(tmp >= 0)
                    tmp += c[k];
                else
                    tmp = c[k];
                if(sum < tmp)
                    sum = tmp;
            }
        }
    }

    cout << "矩阵最大子矩阵和为:" << sum;
}
/*
测试数据:
4 4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
*/

参考博客:https://blog.csdn.net/Double2hao/article/details/51727420?tdsourcetag=s_pctim_aiomsg

おすすめ

転載: blog.csdn.net/qq_42650433/article/details/106505361