#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include <stdio.h>
#include<math.h>
void main()
{
int i,j,ir,ix,k,l,i1,j1;/*ir是列数,ix是矩阵行数*/
int sum1, sum2=0,sum3=0;
int juzhen[10][10];
int sup[10];/*辅助矩阵,用来把同列的元素加在一起,然后求最大部分和*/
scanf("%d", &ix);/*输入行数*/
scanf("%d", &ir);/*输入列数*/
for(i=0;i<ix;i++)
for (j = 0; j < ir; j++)
{
scanf("%d", &juzhen[i][j]); /*输入矩阵内容*/
}
for (k = 0; k < ix; k++)/*从第一行开始往下加,每加完一行求一次最大部分和,用sum2记录目前找出的最大的部分和,sum1记录每一行的部分和*/
{
for (l = 0; l < 10; l++) /*sup数组初始化*/
sup[l] = 0;
for (j=k; j< ix; j++)
{
for (i = 0; i < ir; i++)
{
sup[i] = sup[i] + juzhen[j][i];
}
for (i1 = 0; i1 < ir; i1++)
{
sum1 = 0;
for (j1 = i1; j1 < ir; j1++)
{
sum1 = sum1 + sup[j1];
if (sum1 > sum2)
sum2 = sum1;
}
}
}
}
printf("%d", sum2);
}
/*思路,先把二维数组压缩为一维数组,即把同列元素求和压缩为一行,然后对一维数组求最大的部分和
注意,压缩为一维数组时要把所有的情况全部考虑进去,一遍一遍的加,第一次从第一行开始往下加,每加完一行就求一次最大部分和
然后把最大的记下来,每当有比其更大的就替换,第二次从第二行开始往下加,这样就可以把所有的可能子矩阵都包含进去了*/
/*举例
输入:
3 4
-3 5 -1 5
2 4 -2 4
-1 3 -1 3
********************
初始sum2=0
k=0时
第一行sup为{-3、5、-1、5},sum1(部分和)最大为5+(-1)+5=9,sum1>sum2,所以sum2=sum1(将sum2赋值为9)
第二行加上来以后,sup为{-1,9,-3,9},sum1最大为9+(-3)+9=15,sum1>sum2,所以sum2=15
第三行加上来以后,sup为{-2,12,-4,12},sum1最大为12+(-4)+12=20,sum1>sum2,所以sum2=20
k=1时
从第二行开始加,即sup为{2,4,-2 4},sum1最大为8
第三行加上来后,sup{1,7,-3,7},sum1最大为12
k=2时
从第三行开始加,sup{-1,3,-1,3},sum1最大为5
故最后得到的最大矩阵和为20
这其中求sup的最大部分和的思路也是类似的
以{-2,12,-4,12}举例,初始sum1为0,sum2由上可知为15
首先是第一遍寻找,-2+12=10;-2+12+(-4)=6;-2+12+(-4)+12=18;此时18>15,所以将sum2赋值为18;
ok,然后是第二遍寻找,这次从12开始(第二个元素)。
12+(-4)=8;12+(-4)+12=20;此时20>18,所以将sum2赋值为20
第三遍第四遍依此类推。
类似的,在上面,k=0时找寻的最大部分和有可能来自于(第一行)的组合,也有可能来自于(第一行,第二行)的组合,也有可能来自于(第一行,第二行,第三行)的组合,而当k=1时,则从第二行开始寻找最大部分和。因为子矩阵肯定也是连续的,所以这样可以囊括所有的情况。
。
最后感谢社区大佬帖子内提供的思路。