这题 的题意想必大家都知道,我就不多说了,就是一个N*N的矩阵里找一个矩形,使得矩形内的元素值相加最大...........
说实话,这题开始是没思路的,当然用暴力除外,但是无疑暴力是超时的,貌似有点DP的赶脚,后来就有了一点思路
接下来分享两种做法,一种是大佬的0ms过,一种是我自己的46ms过
一言不合直接上代码:
这种方法就是一遍 遍历列长度,将一定长度列上的看成一个元素。然后看成一维数组,自己求最大连续子序列,不断更新最大值就ok了
就比如返回dp(1,2)时
dp(1,2) 的意思是遍历是所有列中的1—2行的长度列上的值 如sum为 9 0 -13 2 ,然后就和求最大子序列和那样,求得在这种遍历1-2行的情况下获得的最大矩形和为9,
然后还遍历到其他所有情况,不断更新最大值...........
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
#define N1 101
int arr[N1][N1];
int N;
int dp(int n,int m)
{
int i,j;
int temp[N1]={0};
for(i=1;i<=N;i++)
{
for(j=n;j<=m;j++)
{
temp[i]+=arr[j][i];//把相应行上的加起来
}
}
int Max=-200;
int sum=0;
for(i=1;i<=N;i++)/*****
{
if(sum>0)
sum+=temp[i];
else
sum=temp[i];
if(sum>Max)
Max=sum;/*********相当于求最大子序列和
}
return Max;
}
int main()
{
int res;
while(~scanf("%d",&N))
{
int i,j;
int Max=-200;
memset(arr,0,sizeof(arr));
for(i=1;i<=N;i++)
for(j=1;j<=N;j++)
scanf("%d",&arr[i][j]);
for(i=1;i<=N;i++)
{
for(j=i;j<=N;j++)
{
res=dp(i,j);/这里就是遍历所求矩形的长是多大,即第几行到第几行
if(res>Max)
Max=res;
}
}
printf("%d\n",Max);
}
return 0;
}
大佬做法:
#include<stdio.h>
#include<string.h>
#define M 105
int b[M][M];// b [ i ][ j ]存的是第j列中前i行的数据之和.求 m 到 n 列的和 即b[k][n]-b[k][m-1]
int main()
{
int i,j,k,sum,ans,s;
int n;
while(~scanf("%d",&n))
{
memset(b,0,sizeof(b));
ans=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
scanf("%d",&k);
b[i][j]=b[i][j-1]+k;
}
for(i=0;i<n;i++) //代码为了方便 i 从 0 开始
{
for(j=i+1;j<=n;j++)
{
sum=0;
for(k=1;k<=n;k++) //利用一维DP的方法求最大字串
{
s=b[k][j]-b[k][i];
if(sum+s<0)
{sum=0;}
else
sum+=s;
if(sum>ans)
ans=sum;
}
}
}
printf("%d\n",ans);
}
return 0;
}
大佬的做法的优点就是遍历给出长度的矩形的时候不用一个一个加了,直接在输入的时候就预处理了.........大佬果然666
![大笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)