問題描述
GZOI隊員們到X鎮遊玩。X鎮是一個很特別的城鎮,它有m+1條東西方向和n+1條南北方向的道路,劃分成m*n個區域,這些區域標從北到南、從西到東的座標標識爲從座標 (1,1) 到座標(m,n)。 GZOI隊員們預先對這m*n個區域打分V(i,j)(分數可正可負)。分數越高表示他們越想到那個地方,越低表示他們越不想去。爲了方便遊玩,隊員們需要選定一個連續的區域集合作爲活動範圍。例如,如果他們選擇了最西北的區域(m1,nl)和最東南(m2,n2)區域(m1<=m2,n1<=n2),那他們的活動範圍是 {D(i,j)|m1<=i<=m2,n1<=j<=n2},其遊覽總分則爲這些活動範圍的區域總分。 GZOI隊員們希望他們活動範圍內的區域的分值總和最大。你的任務是編寫一個程序,求出他們的活動範圍(m1,nl),(m2,n2〉。
輸入
輸入第一行爲整數m(1<=m<=200),n(1<=n<=200),用空格隔開 下面爲m行,每行有n列整數,其中第i行第j列的整數,代表V(i,j),每個整數之間用空格隔開,每個整數的範圍是 [-200000,200000],輸入數據保證這些整數中,至少存在一個正整數。
輸出
輸出只有一行,爲最高的分值。
樣例輸入
4 5
1 -2 3 -4 5
6 7 8 9 10
-11 12 13 14 -15
16 17 18 19 20
樣例輸出
146
算法討論
預處理每行的前綴和,枚舉從哪一列開始,行數從1到n的矩形,若分值小於零,就把ans清零接着做。
#include <cstdio>
#define MAX_N 206
#define LL long long
using namespace std;
int a[MAX_N][MAX_N],f[MAX_N][MAX_N],n,m;
LL s,Max;
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
f[i][j]=f[i][j-1]+a[i][j];
}
for (int k=1;k<=m;k++)
for (int j=k;j<=m;j++)
{
s=0;
for (int i=1;i<=n;i++)
{
s+=(f[i][j]-f[i][k-1]);
Max=max(s,Max);
if (s<0)
s=0;
}
}
printf("%lld",Max);
}