题目大意:给定一个N阶方阵(1<=N<=100),其元素的取值范围为[-127,127]。求其中的一个M*P维子矩阵(1<=M<=100,1<=P<=100),要求使该子矩阵中元素的和最大。
求最大子矩阵,大一的时候一个作业即是这个题目,忘了当时怎么写的了,重写一遍。首先求一维数组的最大子段,也是DP问题。
假设数组arr[SIZE],f[i] 是以“第i个位置为结束点的子段”的最大和。枚举所有位置,即枚举所有 i。注意到 f[i] 是包含 i 位置的最大和子段(假设不包含 i 位置,则在枚举到小于 i 位置(假设为 j 位置)时候已经算出包含 i 位置最大和子段),则有:
f[i] = max(f[i-1], 0)+arr[i]
意思是如果包含 i-1 点的最大和子段小于0,则对包含 i 点的最大和子段没有贡献,f[i] = arr[i]。反之,如果包含 i-1 点的最大和子段大于0,则对包含 i 点的最大和子段有正贡献,则需要加上:f[i] = f[i-1] + arr[i]
int sumSubArray(const int arr[], const int size)
{
int endB=0, sum=MIN_INT;
for (int i=0; i<size; i++)
{
if (endB>0) endB += arr[i];
else endB = arr[i];
if (sum<endB) sum = endB;
}
return sum;
}
这就是用DP解决一位数组的最大和子段。参考
解决二维数组的最大子矩阵,转化为一维的即可。枚举从 i (i从0取到max_row)行到 j (j从i取到max_row)行,temp[SIZE]中的每个元素为第 i 行到第 j 行的每一列的和,对temp[]求最大子段即是对二维数组求最大子矩阵。我的代码如下:
1: #include <iostream>
2: using namespace std;
3: const int MIN_INT = -(1<<15);
4:
5: int sumSubArray(const int arr[], const int size)
6: {
7: int endB=0, sum=MIN_INT;
8: for (int i=0; i<size; i++)
9: {
10: if (endB>0) endB += arr[i];
11: else endB = arr[i];
12:
13: if (sum<endB) sum = endB;
14: }
15: return sum;
16: }
17:
18: int sumSubArray2(int** arr, const int row, const int col)
19: {
20: int* temp = new int[col];
21: int sum = MIN_INT;
22: for (int i=0; i<row; i++)
23: {
24: for (int j=i; j<row; j++)
25: {
26: for (int t=0; t<col; t++)
27: temp[t] = 0;
28:
29: for (int k=i; k<=j; k++)
30: {
31: for (int pos=0; pos<col; pos++)
32: temp[pos] += arr[k][pos];
33: }
34: int sumTemp = sumSubArray(temp, col);
35: if (sum<sumTemp)
36: sum = sumTemp;
37: }
38: }
39: delete[] temp;
40: return sum;
41: }
42:
43: int main()
44: {
45: int arrSize;
46: cin >> arrSize;
47: if (arrSize<=0)
48: return -1;
49: int** arr = new int* [arrSize];
50: arr[0] = new int[arrSize*arrSize];
51: for (int i=1; i<arrSize; i++)
52: arr[i] = arr[i-1] + arrSize;
53:
54: for (int i=0; i<arrSize; i++)
55: {
56: for (int j=0; j<arrSize; j++)
57: cin >> arr[i][j];
58: }
59:
60: int sum = sumSubArray2(arr, arrSize, arrSize);
61: cout << sum << endl;
62:
63: delete[] arr[0];
64: delete[] arr;
65: return 0;
66: }