AcWing 126. 最大的和(二維字首和)
阿新 • • 發佈:2021-02-01
給定一個包含整數的二維矩陣,子矩形是位於整個陣列內的任何大小為1 * 1或更大的連續子陣列。
矩形的總和是該矩形中所有元素的總和。
在這個問題中,具有最大和的子矩形被稱為最大子矩形。
例如,下列陣列:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
其最大子矩形為:
9 2
-4 1
-1 8
它擁有最大和15。
輸入格式
輸入中將包含一個N*N的整數陣列。
第一行只輸入一個整數N,表示方形二維陣列的大小。
從第二行開始,輸入由空格和換行符隔開的N2個整數,它們即為二維陣列中的N2個元素,輸入順序從二維陣列的第一行開始向下逐行輸入,同一行資料從左向右逐個輸入。
陣列中的數字會保持在[-127,127]的範圍內。
輸出格式
輸出一個整數,代表最大子矩形的總和。
資料範圍
1≤N≤100
輸入樣例:
4
0 -2 -7 0 9 2 -6 2
-4 1 -4 1 -1
8 0 -2
輸出樣例:
15
思路:
列舉矩形的對頂角左邊,需要四重迴圈,再用二維字首和在O(1)的時間內求出矩形的和,總的複雜度是O(n^4)。參考下一維連續和的問題,若dp[i]為以i為結尾的最大連續和,則當dp[i-1] > 0時,dp[i]就需要加上dp[i - 1],否則不加。現在將矩形的每一列抽象為一維連續和問題的一個數,之前的若干列和為正數,就加上它,否則不加。需要列舉列所在的起點和終點,以及橫向的一層遍歷,總的複雜度為立方級別的。
答案:
#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define lowbit(x) x&(-x)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define PI acos(-1)
#define pb push_back
#define eps 1e-6
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
const int M = 1e3 + 10;
using namespace std;
int dp[M][M];
void solve(){
int n;
cin>>n;
rep(i,1,n){
rep(j,1,n){
cin>>dp[i][j];
dp[i][j]+=dp[i-1][j]; ///列字首和
}
}
int maxn=INT_MIN;
rep(i,1,n){
rep(j,i,n){
int res=0;
rep(k,1,n){
res+=dp[j][k]-dp[i-1][k];
if(res>maxn) maxn=res;
if(res<0) res=0;
}
}
}
cout<<maxn<<endl;
}
int main()
{
solve();
return 0;
}