【算法分析】
二维数组方法
先把数据存储到二维数组 map[i][j],然后采用前缀和的方法把 map[i][j] 转变成第 i 行前 j 列的值。然后定义两个游标top(1<=top<=n)和trail(top<=trail<=n),目的是遍历所有的列区域。然后遍历每一行,找出最大值maxn。
【参考代码】
#include <iostream>
#include <algorithm>
using namespace std;
int map[102][102];
int main(int argc, char *argv[])
{
int n,m,maxn=-10000;
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
cin>>m;
map[i][j]=map[i][j-1]+m;
}
for(int top=1;top<=n;top++)
for(int tail=top;tail<=n;tail++){ //遍历所有的列区域
int sum=0;
for(int k=1;k<=n;k++){ //遍历每一行
sum+=map[k][tail]-map[k][top-1];
maxn=max(maxn,sum);
sum=max(0,sum); //如果该区域不是正值,就不要这个区域。
}
}
cout<<maxn<<endl;
return 0;
}
一维数组的方法
方法和二维数组方法类似,只是把二维数组压缩成一维数组dp[k],dp[k]代表该区域前k列的和。然后遍历每个区域求出最大值。
#include<bits/stdc++.h>
using namespace std;
const int N=1001;
int data[N][N],dp[N],n,maxnum=INT_MIN;
int search(){
int sn=0,ln=INT_MIN;
for(int i=1;i<=n;++i){
if(sn>0){
sn+=dp[i]; //如果是正值就累加,如果不是就以当前区域值开始计算
}else{
sn=dp[i];
}
ln=max(sn,ln);
}
return ln;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
scanf("%d",&data[i][j]);
}
}
for(int i=1;i<=n;++i){ //行区域开始
memset(dp,0,sizeof(dp));
for(int j=i;j<=n;++j){ //行区域结束
for(int k=1;k<=n;++k){ //dp[k]表示该区域前K列的值
dp[k]+=data[j][k];
}
int temp=search();
maxnum=max(maxnum,temp);
}
}
cout<<maxnum<<endl;
return 0;
}