1. 程式人生 > >計蒜客:最大子陣

計蒜客:最大子陣

問題:

給定一個 n × m n \times m 的矩陣 A A ,求 A

A 中的一個非空子矩陣,使這個子矩陣中的元素和最大。
其中, A A 的子矩陣指在 A A 中行和列均連續的一部分。

輸入格式:


輸入的第一行包含兩個整數 n , m ( 1 n , m
50 ) n,m(1 \leq n,m \leq 50)
,分別表示矩陣 A A 的行數和列數。
接下來 n n 行,每行 m m 個整數,表示矩陣 A i , j ( 1000 A i , j 1000 ) A_{i,j}(-1000 \leq A_{i,j} \leq 1000)

輸出格式:
輸出一行,包含一個整數,表示 A A 中最大子矩陣的元素和。

樣例輸入:

3 3

2 -4 1

-1 2 1

4 -2 2

樣例輸出:

6

題解:

思路:第一映像是暴力列舉,不過顯然會超時,然後就想到了DP(動態規劃)。其實因為矩陣肯定是對齊的,所以如我們將兩行加起來求最大子陣列就可以得到一個行數為2的子矩陣。所以問題就轉化成了求一個數組的最大子陣列和。然後就是列舉第i行到第j行相加得到的陣列了。注意res的值不能設為0,因為可能最後的結果是負數。

知識點:

子矩陣:
是在矩陣選取部分行、列所組成的新矩陣。
例如:
在這裡插入圖片描述
在這裡插入圖片描述
它亦可用A(3;2)表示,顯示除掉第3行和第2列的餘下的矩陣。這兩種方法比較常用,但還是沒有標準的方法表示子矩陣。

memset()函式及其作用

#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int N, M;
int a[105][105];
int dp[105];
int getMax(int a[], int M) 
{
	int max = a[0], temp = 0;
	for (int i = 0; i < M; i++) 
	{
		if (temp > 0) 
			temp += a[i];
		else 
			temp = a[i];
		max = max > temp ? max : temp;
	}
	return max;
}
int main(void)
{
	cout << "請輸入矩陣的行和列:";
	cin >> N >> M;
	cout << "請輸入矩陣的資料:" << endl;
	for (int i = 0; i < N; ++i) 
	{
		for (int j = 0; j < M; ++j) 
		{
			cin >> a[i][j];
		}
	}
	int Max = a[0][0], temp;
	for (int i = 0; i < N; i++)
	{
		memset(dp, 0, sizeof(dp));
		for (int j = i; j < N; j++)
		{
			for (int k = 0; k < M; k++)
			{
				dp[k] += a[j][k];
			}
			temp = getMax(dp, M);
			Max = Max > temp ? Max : temp;
		}
	}
	cout << "最大值為:" << Max << endl;
	system("pause");
	return 0;
}