蓝桥杯准备——计蒜客·求最大子阵

这是这道题目:

给定一个 n \times mn×m 的矩阵 AA,求 AA 中的一个非空子矩阵,使这个子矩阵中的元素和最大。其中,AA 的子矩阵指在 AA 中行和列均连续的一部分。

输入格式

输入的第一行包含两个整数 n,m(1 \leq n,m \leq 50)n,m(1≤n,m≤50),分别表示矩阵 AA 的行数和列数。

接下来 nn 行,每行 mm 个整数,表示矩阵 A_{i,j}(-1000 \leq A_{i,j} \leq 1000)Ai,j​(−1000≤Ai,j​≤1000)。

输出格式

输出一行,包含一个整数,表示 AA 中最大子矩阵的元素和。

样例输入

3 3
2 -4 1
-1 2 1
4 -2 2

样例输出

6

暴力穷举也是可以过的,但是网上查了下,别人用的都是动态规划。我这里参考了这位博主的文章:动态规划(最大子矩阵)

这是最后的代码:

#include 
#include 
using namespace std;

int maxsub(int a[], int n)
{
	int i, max = a[0], b = 0;
	for (i = 0; i < n; i++)
	{
		if (b + a[i] >= a[i])	//当n-1的最大字段和+a[i]>=原来的最大字段和
			b += a[i];	//则n的最大字段和为b+a[i]
		else	//否则,就是a[i]
			b = a[i];
		if (b > max)	//找到最大的最大字段和
			max = b;
	}
	return max;
}

int main()
{
	int n, i, j, k, maxsubrec, maxsubarr, m;
	int dp[101][101], arr[101];
	cin >> n >> m;
	for (i = 0; i < n; i++)
		for (j = 0; j < m; j++)
			cin >> dp[i][j];
	maxsubrec = dp[0][0];
	for (i = 0; i < n; i++)	//i用于标识从哪行开始,依次选择行
	{
		memset(arr, 0, sizeof(arr));
		for (j = i; j < n; j++)	//从第i行开始,j为选择几行
		{
			for (k = 0; k < m; k++)	//从1列选择到m列,压缩行
				arr[k] += dp[j][k];
			maxsubarr = maxsub(arr, m);	//从每一个压缩行中选择最大字段和
			if (maxsubarr > maxsubrec) maxsubrec = maxsubarr;
		}
	}
	cout << maxsubrec << endl;
	return 0;
}

 

你可能感兴趣的:(十一届蓝桥杯复习准备,算法理论的学习(C++))