UVA-108

題意

給一個N*N的int矩陣,求出全部子矩陣中的最大和。ios

解法:

蠻力算法(超時):

        枚舉全部左上角起點(startRow,startCow)O(N^2)和右下角終點(endRow, endCow)O(N^2),求出子矩陣的和O(N^2)。複雜度O(N^2)* O(N^2)* O(N^2)= O(N^6)。c++

解法1:

      動態規劃。算法

memo[i][j] = memo[i - 1][j] + memo[i][j - 1] - memo[i - 1][j - 1] + data[i][j]數組

其中memo[i][j]表示(0,0)到(i,j)之間的和,data[i][j]表示第i行j列的數字。spa

複雜度O(N^2)* O(N^2)= O(N^4)code

#include <iostream>
#include <algorithm>
using namespace std;
#define INT_MIN     (-2147483647 - 1) 
int main()
{
	int N, memo[101][101], ms = INT_MIN; cin >> N;
	for (int i = 0; i <= N; i++) memo[i][0] = memo[0][i] = 0;
	for (int i = 1; i <= N; i++)  for (int j = 1; j <= N; j++)
	{
		int t; cin >> t;
		memo[i][j] = memo[i - 1][j] + memo[i][j - 1] - memo[i - 1][j - 1] + t;
	}
	for (int sr = 1; sr <= N; sr++)  for (int sc = 1; sc <= N; sc++)
	for (int er = sr; er <= N; er++)  for (int ec = sc; ec <= N; ec++)
		ms = max(ms, memo[er][ec] - memo[sr - 1][ec] - memo[er][sc - 1] + memo[sr - 1][sc - 1]);
	cout << ms << endl;
	return 0;
}

解法2:

     仍是動態規劃,只不過將二維降到一維求解。 ci

    枚舉全部起點的行和終點的行O(N^2) ,一維數組squashed[]記錄起點行和終點行之間的各列之和,it

squashed[c] += memo[er][c]io

以後對squashed數組這個一維空間上計算,至關於枚舉了起點的列和終點的列,但因爲是一維空間,所以複雜度O(N)class

總體複雜度O(N^2) * O(N) = O(N^3)。

#include <iostream>
#include <algorithm>
using namespace std;
#define INT_MIN     (-2147483647 - 1) 
int main()
{
	int N, memo[100][100], ms = INT_MIN; cin >> N;
	for (int i = 0; i < N; i++) for (int j = 0; j < N; j++)  cin >> memo[i][j];
	for (int sr = 0; sr < N; sr++)
	{
		int squashed[100] = {0};
		for (int er = sr, sum = INT_MIN; er < N; er++)
		{
			for (int c = 0; c < N; c++) squashed[c] += memo[er][c];
			for (int c = 0, candidate = 0; c < N; c++)
			{
				candidate += squashed[c];
				sum = max(sum, candidate);
				candidate = max(0, candidate);
			}
			ms = max(ms, sum);
		}
	}
	cout << ms << endl;
	return 0;
}