您的位置:首页 > 编程语言 > C语言/C++

百度笔试编程题:最大子阵和(C++)

2016-09-13 21:39 260 查看

题目:

问题:

求一个M*N的矩阵的最大子矩阵和。

比如在如下这个矩阵中:

0 -2 -7 0

9 2 -6 2

-4 1 -4 1

-1 8 0 -2

拥有最大和的子矩阵为:

9 2

-4 1

-1 8

其和为15。

思路:

首先,这个子矩阵可以是任意大小的,而且起始点也可以在任何地方,所以,要把最大子矩阵找出来,我们要考虑多种情况。

假定原始矩阵的行数为M,那么对于子矩阵,它的行数可以是1到M的任何一个数,而且,对于一个K行(K < M)的子矩阵,它的第一行可以是原始矩阵的第1行到 M - K + 1 的任意一行。

例子:

对于上面的矩阵,如果子矩阵的行数是2,那么它可以是下面几个矩阵的子矩阵:

0 -2 -7 0

9 2 -6 2

或者

9 2 -6 2

-4 1 -4 1

或者

-4 1 -4 1

-1 8 0 -2

在每一种情况里(我们这里有三种),我们还要找出一个最大的子矩阵,当然,这只是一种情况的最大子矩阵(局部最大),不一定是global最大。但是,如果我们知道每一种情况的最大,要找出global最大,那就小菜一碟儿了。

在讲在一个特殊情况下求最大子矩阵之前,先讲一个事实:

假设这个最大子矩阵的维数是一维,要找出最大子矩阵, 原理与求“最大子段和问题” 是一样的。最大子段和问题的递推公式是 b[j]=max{b[j-1]+a[j], a[j]},b[j] 指的是从0开始到j的最大子段和。

例子:

假设原始矩阵为:[9, 2, -6, 2], 那么b[] = {9, 11, 5, 7}, 那么最大字段和为11, 如果找最大子矩阵的话,那么这个子矩阵是 [9, 2]

答案:

#include <iostream>

using namespace std;

const int MAX = 100;
int p[MAX][MAX];

bool flag;

int main(){

int T;
scanf("%d",&T);

while(T--) {

int n,m,k,max,sum,min;

while(~scanf("%d%d",&n,&m)){

for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j){
p[0][j] = 0;
scanf("%d",&k);
p[i][j] = p[i-1][j] + k;
}
}

max = 0;flag = false;min = -1005;
for(int i = 1; i <= n; ++i){
for(int j = i ; j <= n; ++j){

sum = 0;
for(int r = 1; r <= m; ++r){

k = p[j][r] -p[i-1][r];
if(sum > 0)
sum += k;
else {
sum = k;
if(!flag && sum > min)
min = sum;
}
if(sum > max){
max = sum;
flag = true;
}
}

}
}
if(!flag)
max = min;

printf("%d\n",max);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ 笔试 编程 百度