1146. Maximum Sum URAL 解题报告
给一个矩阵,求最大的子矩阵和,矩阵元素有正有负!
这貌似是当年刚上ACM选修课的时候老师讲的一道题目,但是一直没想明白怎么做,今天看的时候也是发怵,一直想搜解题报告,但是强忍住没有搜,也幸亏没有搜,现在做着做着就做出来了,感觉特别棒,找到了当初做ACM的感觉! 也许这道题不是很难,但是其中的思想我觉得还是有必要整理一下; 首先,我动手写这个题的时候还是没有完全想明白,做着做着发现自己的思路出现问题了,怎么办呢,于是想到再加一层循环控制另外一个因素,当时这个题有两个限制因素! 刚开始只处理了一个限制因素,幸亏也没想明白其实这两个题有两个限制因素,某则我也不敢做下去了,看来有时候,不一定非得把东西都准备好才开始动手! 先下手为强! 两个因素限制的问题,先考虑一个因素,搞掉他之后在琢磨另外一个问题!
思路:
cnt[j]表示当前行前j个元素的和,mval[i][j]表示从开头到map[i][j]这个矩阵的最大和,其实有两种来源,不是cnt[j]本身就是mval[i-1][j]+cnt[j] ;
但是矩阵并非都包含map[i][1]啊,怎么办呢? 再加一个for控制这一限制条件,就ok了;
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 110
int n,m,k;
int map[MAX][MAX];
int cnt[MAX];
int mval[MAX][MAX];
int ans;
int main()
{
memset(map,0,sizeof(map));
memset(cnt,0,sizeof(cnt));
memset(mval,0,sizeof(mval));
scanf("%d",&n);
ans=-1000000;///这里的初始化很关键,
for(int i=1; i<=n; ++i)
{
for(int j=1; j<=n; ++j)
scanf("%d",&map[i][j]);
}
for(int k=1; k<=n; ++k)
{///本来没想到第一层循环,但是做着做着发信啊不对,怎么办呢?当时想到了加一层循环…… 果然解决问题了
///思考问题的时候如果一开始就想到两层循环不行的话,那就惨了,这个问题可能就解决不了了,但是做着做着,
///发现一个问题解决一个问题,哎,竟然做对了;虽然一开始没想出来…… 这个感觉太棒了
memset(mval,0,sizeof(mval));
for(int i=1; i<=n; i++)
{
memset(cnt,0,sizeof(cnt));
for(int j=k; j<=n; ++j)
{
cnt[j]=cnt[j-1]+map[i][j];
mval[i][j]=max(cnt[j],mval[i-1][j]+cnt[j]);
ans=max(ans,mval[i][j]);
}
}
}
printf("%d\n",ans);///
return 0;
}