Maximum Sum
Maximum Sum
| Time Limit: 1000MS | Memory Limit: 65535KB |
| Submissions: 26 | Accepted: 18 |
Sample Input
4 0 -2 -7 0
9 2 -6 2 -4 1 -4 1
-1 8 0 -2
Sample Output
15
分析:
【解法一】
题意很清晰,首先用人人都能想到的方法,确定个起点,在确定个终点,将它们形成矩形内的数的和算出来就行了,六个for语句,时间复杂度可想而知;而且现在n在100内,如果n再大一点,显然就通不过了
代码如下:
# include<stdio.h> #define inf 99999 int main() { int n; int i,j,e,f,l,m; int sum,Maxnum=-inf; int Map[102][102]; scanf("%d",&n); for(i=0;i<n;i++) for(j=0;j<n;j++) scanf("%d",&Map[i][j]); for(i=0;i<n;i++)//确定起点 { for(j=0;j<n;j++) { for(e=i;e<n;e++)//确定终点 { for(f=j;f<n;f++) { sum=0; for(l=i;l<=e;l++)//将和算出来 for(m=j;m<=f;m++) sum+=Map[l][m]; if(sum>Maxnum) Maxnum=sum; } } } } printf("%d\n",Maxnum); return 0; }
由于对于每行而言,每次都是在前面的基础上加了一列,因此可以优化一下
代码如下:
# include<stdio.h> #define inf 99999 int main() { int n; int i,j,e,f,l; int sum,Maxnum=-inf; int Map[102][102]; scanf("%d",&n); for(i=0;i<n;i++) for(j=0;j<n;j++) scanf("%d",&Map[i][j]); for(i=0;i<n;i++)//确定起点 { for(j=0;j<n;j++) { for(e=i;e<n;e++)//确定终点 { sum=0;//换一行就清零,重新计算 for(f=j;f<n;f++) { for(l=i;l<=e;l++)//在前面的基础上加一列 sum+=Map[l][f]; if(sum>Maxnum) Maxnum=sum; } } } } printf("%d\n",Maxnum); return 0; }
【解法二】
即使优化了,n大了,肯定也不行;那再思考另一种算法吧
考虑起始点和终点,不得不用上4个for语句,那如果考虑到起始行和末尾行,两个for语句就行了
代码如下:
# include<stdio.h> # include<string.h> #define inf 99999 int n; int solve(int dp[]) { int i; int add=-inf,sum=-inf; for(i=0;i<n;i++) { if(add>0) add+=dp[i]; else add=dp[i]; if(add>sum) sum=add; } return sum; } int main() { int i,j,e; int sum,Maxnum=-inf; int Map[102][102],dp[102]; scanf("%d",&n); for(i=0;i<n;i++) for(j=0;j<n;j++) scanf("%d",&Map[i][j]); for(i=0;i<n;i++)//调整起始行 { memset(dp,0,sizeof(dp)); for(j=i;j<n;j++)//移动末尾行 { for(e=0;e<n;e++)//移动一次加一次 { dp[e]+=Map[j][e]; } sum=solve(dp);//获得第i行到第j行(含有第i行和第j行)上的最大子矩阵 if(sum>Maxnum)//并同时判断一次 Maxnum=sum; } } printf("%d\n",Maxnum); return 0; }
浙公网安备 33010602011771号