題目描述
為了更好的備戰 NOIP2013,電腦組的幾個女孩子 LYQ,ZSC,ZHQ 認為,我們不光需要機房,我們還需要運動,於是就決定找校長申請一塊電腦組的課餘運動場地,聽說她們都是電腦組的高手,校長沒有馬上答應他們,而是先給她們出了一道數學題,並且告訴她們:你們能獲得的運動場地的面積就是你們能找到的這個最大的數字。
校長先給他們一個n*n 矩陣。要求矩陣中最大加權矩形,即矩陣的每一個元素都有一權值,權值定義在整數集上。從中找一矩形,矩形大小無限制,是其中包含的所有元素的和最大 。矩陣的每個元素屬於 [-127,127],例如
0 –2 –7 0
9 2 –6 2
-4 1 –4 1
-1 8 0 –2
在左下角:
9 2
-4 1
-1 8
和為 15。
幾個女孩子有點犯難了,於是就找到了電腦組精打細算的 HZH,TZY 小朋友幫忙計算,但是遺憾的是他們的答案都不一樣,涉及土地的事情我們可不能含糊,你能幫忙計算出校長所給的矩形中加權和最大的矩形嗎?
輸入格式
第一行:n,接下來是 n 行 n 列的矩陣。
輸出格式
最大矩形(子矩陣)的和。
樣例 #1
樣例輸入 #1
4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
樣例輸出 #1
15
提示
1 <=n<=120
Kadane演算法
這是一個經典的求解一維最大子陣列和的演算法,時間複雜度是 O(n)。
過程:我們遍歷所有可能的左右邊界(列),將這兩列之間的所有行元素累加起來形成一個新的陣列。
對於每一個累加的陣列,應用 Kadane 演算法來尋找這個一維陣列的最大子陣列和。
程式碼示例
#include <iostream>
#include <climits>
using namespace std;
// Kadane演算法:求一維陣列中連續子陣列的最大和
int kadane(int arr[], int n) {
int max_so_far = arr[0];
int max_ending_here = 0;
for (int i = 0; i < n; i++) {
max_ending_here += arr[i];
if (max_ending_here > max_so_far) {
max_so_far = max_ending_here;
}
if (max_ending_here < 0) {
max_ending_here = 0;
}
}
return max_so_far;
}
// 求最大加權矩形的和,這是主要的求解函式,它透過列舉所有的列對 (left, right),並將這兩列之間的元素累加到 temp 陣列中。然後在 temp 陣列上應用 Kadane 演算法,計算該區域內最大加權矩形的和。
int maxSum(int matrix[][120], int n) {
int max_sum = INT_MIN;
// 遍歷所有列對 (left, right)
for (int left = 0; left < n; ++left) {
int temp[120] = {0}; // 儲存每列加和後的臨時陣列
for (int right = left; right < n; ++right) {
// 將從left列到right列的每行元素累加到temp陣列
for (int i = 0; i < n; ++i) {
temp[i] += matrix[i][right];
}
// 在temp陣列上應用Kadane演算法,找出最大和
int current_max = kadane(temp, n);
max_sum = max(max_sum, current_max); // 更新全域性最大和
}
}
return max_sum;
}
int main() {
int n;
cin >> n;
int matrix[120][120];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
cin >> matrix[i][j];
}
}
// 輸出最大加權矩形的和
cout << maxSum(matrix, n) << endl;
return 0;
}