#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
#include <set>
using namespace std;
/*
问题:
输入:
2 3(行和列)
1 -2 3
-4 5 6
3 5
9 -8 1 3 -2
-3 7 6 -2 4
6 -4 -4 8 -7
输出:
12
-2 3
5 6
19
9 -8 1 3
-3 7 6 -2
6 -4 -4 8
*/
//求一维子数组最大连续和
int maxSubArray(vector<int>& nums)
{
if(nums.empty())
{
return 0;
}
int size = nums.size();
int sum = 0;
int maxSum = 0;
for(int i = 0 ; i < size ; i++)
{
sum = max(nums.at(i) , sum + nums.at(i));
maxSum = max(maxSum , sum);
}
return maxSum;
}
//求一维子数组中最大连续和<k的最大值,先不断求累加和数组,然后
//设需要找到的数为val , 即val < k 且val是最接近的,等同于求这样的累加和的位置
//寻找之前的累加和val > 当前元素的累加和curSum - k 的位置,然后找到val对应位置为p,用curSum - val,即可得到位置p到当前位置累加和<k的最大值
//即val (min) > curSum - k, curSum - val(min) < k
int maxSubArray_LessK(vector<int>& nums , int k)
{
if(nums.empty())
{
return 0;
}
int curSum = 0 ;
int best = 0;
int size = nums.size();
set<int> sums;
for(int i = 0 ; i < size ; i++)
{
curSum += nums.at(i);
auto it = sums.upper_bound(curSum - k);//找到前面某元素的累加和略大于curSum-k中的最小值val,从而保证该元素与直到当前元素的累加和(curSum - val)略小于k
if(it != sums.end() )
{
best = max(best , curSum - *it);
}
sums.insert(curSum);
}
return best;
}
int maxSubArray_NoMoreThanK(vector<int>& nums , int k)
{
if(nums.empty())
{
return 0;
}
int curSum = 0 ;
int best = INT_MIN;
int size = nums.size();
set<int> sums;
sums.insert(0);//确保如果当前元素的累加和 < k,那么当前元素的累加和是一个解
for(int i = 0 ; i < size ; i++)
{
curSum += nums.at(i);
auto it = sums.lower_bound(curSum - k);//找到前面某元素的累加和略大于curSum-k中的最小值val,从而保证该元素与直到当前元素的累加和(curSum - val)略小于k
if(it != sums.end() )
{
best = max(best , curSum - *it);
}
sums.insert(curSum);
}
return best;
}
class Solution {
public:
int maxSumSubmatrix(vector<vector<int>>& matrix, int k)
{
if(matrix.empty())
{
return 0;
}
int row = matrix.size();
int col = matrix.at(0).size();
int maxSum = INT_MIN;
for(int i = 0 ; i < col ; i++)
{
vector<int> nums(row , 0);
for(int j = i ; j < col ; j++)
{
set<int> sums;
sums.insert(0);//用于插入累加和元素
int curSum = 0;
int curMax = INT_MIN;
//计算从第i列到第j列中,每一行的元素和,将所有每一行的元素和作为一维子数组,然后求该子数组最大连续和
for(int x = 0; x < row ; x++)
{
//累加了上一列中同一行的元素
nums.at(x) += matrix.at(x).at(j);
curSum += nums.at(x);//计算累加和
auto it = sums.lower_bound(curSum - k);//寻找VALmin >= curSum - k ,那么curSum - VALmin <= k,计算出从寻找位置到当前位置最接近k的累加和
if(it != sums.end())
{
curMax = max(curMax , curSum - *it);
}
sums.insert(curSum);
}
maxSum = max(maxSum , curMax);
}
}
return maxSum;
}
};
//求二维连续子矩阵的最大和,采用遍历当前行,尝试将当前行及其以下部分的行中,每一列元素累加,转化为求一维中最大连续子数组之和
int maxSubMatrix(vector<vector<int> >& matrix)
{
if(matrix.empty())
{
return 0;
}
int row = matrix.size();
int col = matrix.at(0).size();
int maxSum = INT_MIN;
for(int i = 0 ; i < row ; i++)
{
vector<int> nums(col , 0);
for(int j = i ; j < row ; j++)
{
//计算从第i行到第j行中,每一列的元素和,将所有每一列的元素和作为一维子数组,然后求该子数组最大连续和
for(int k = 0; k < col ; k++)
{
//累加了上一行中同一列的元素
nums.at(k) += matrix.at(j).at(k);
}
//求连续几行之间的最大连续和
int sum = maxSubArray(nums);
maxSum = max(maxSum , sum);
}
}
return maxSum;
}
//以列主要计算方面,将两列之间同一行的元素累加,转化为一维数组求最大连续和,行n,列m,时间复杂度为O(m^2 * n)
int maxSubMatrix_BaseColumn(vector<vector<int> >& matrix)
{
if(matrix.empty())
{
return 0;
}
int row = matrix.size();
int col = matrix.at(0).size();
int maxSum = INT_MIN;
for(int i = 0 ; i < col ; i++)
{
vector<int> nums(row , 0);
for(int j = i ; j < col ; j++)
{
//计算从第i列到第j列中,每一行的元素和,将所有每一行的元素和作为一维子数组,然后求该子数组最大连续和
for(int k = 0; k < row ; k++)
{
//累加了上一列中同一行的元素
nums.at(k) += matrix.at(k).at(j);
}
//求连续几行之间的最大连续和
int sum = maxSubArray(nums);
maxSum = max(maxSum , sum);
}
}
return maxSum;
}
void process()
{
vector<vector<int> > matrix;
int value;
int row;
int col;
int result;
while(cin >> row >> col )
{
matrix.clear();
for(int i = 0 ; i < row ; i++)
{
vector<int> nums;
for(int j = 0 ; j < col ; j++)
{
cin >> value;
nums.push_back(value);
}
matrix.push_back(nums);
}
result = maxSubMatrix_BaseColumn(matrix);
cout << result << endl;;
}
}
void test()
{
set<int> setNum;
setNum.insert(1);
int k = 10;
int curNum = 1;
auto it = setNum.lower_bound(curNum - k);
int best = 0;
if(it != setNum.end())
{
best = max(best , curNum - *it);
}
setNum.insert(curNum);
}
int main(int argc , char* argv[])
{
process();
//test();
getchar();
return 0;
}