注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Hao的博客

I'm on my way……

 
 
 

日志

 
 
 
 

POJ1050 最大子矩形  

2009-04-03 15:05:10|  分类: Algorithm discov |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
To the Max
Time Limit: 1000MS  Memory Limit: 10000K
Total Submissions: 13544  Accepted: 6813
Description
Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous sub-array of size 1*1 or greater located within the whole array. The sum of a rectangle is the sum of all the elements in that rectangle. In this problem the sub-rectangle with the largest sum is referred to as the maximal sub-rectangle.
As an example, the maximal sub-rectangle of the array:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
is in the lower left corner:
9 2
-4 1
-1 8
and has a sum of 15.
Input
The input consists of an N * N array of integers. The input begins with a single positive integer N on a line by itself, indicating the size of the square two-dimensional array. This is followed by N^2 integers separated by whitespace (spaces and newlines). These are the N^2 integers of the array, presented in row-major order. That is, all numbers in the first row, left to right, then all numbers in the second row, left to right, etc. N may be as large as 100. The numbers in the array will be in the range [-127,127].
Output
Output the sum of the maximal sub-rectangle.
Sample Input
4
0 -2 -7 0 9 2 -6 2
-4 1 -4  1 -1
8  0 -2
Sample Output
15
Source
 
题目大意:给定一个二维整型数组,数组中的元素可正可负。由这个二维数组所构成的矩形中,存在一个最大的子矩形。其中最大子矩形定义为矩形的所有元素之和最大,要求输出这个值。

主要思想:

1.从二维的角度去看这道题目有些复杂,就先考虑一维中的类似情况——求一维数组中和最大的子串。假设当前的串为...abcde...,如果...+a+b<0,则最大的子串或者是...ab中的最大子串、或者是c+d+e+...中的最大子串,显然一个整数加上一个负数一定小于这个整数,将temp更新为c。如果...+a+b>0,则将c加进来更新temp的值。如果temp>MAX就更新MAX,这样只要每加进一个元素就更新temp并检查MAX是否需要更新,就能得到最大子串的和。

2.现在回到二维的情况,只要将矩形高压缩,就变成了一维的情况了。也就是说,如果考虑第i行到第j行的矩形,那么只需要知道矩形的每一列从第i行到第j行的和,就可以用一维的算法去求解在该范围内的最大子矩形了。

代码如下:

#include<iostream>
#define N 100
#define MAX (1<<20)
using namespace std;
int colSum[N][N];  //colSum[i][j]表示第j列中从第0行到第i行的和
int main(){
    int n;
    int i,j,k;
    int sum[N]={0},max,temp,result;
    while(cin>>n){
        for(i=0;i<n;i++)
            for(j=0;j<n;j++){  //初始化colSum[i][j]
                cin>>colSum[i][j];
                if(i!=0)colSum[i][j]+=colSum[i-1][j];
            }
        result=-MAX;  //将result赋值为最小值
        for(k=0;k<n;k++)
            for(i=k;i<n;i++){
                for(j=0;j<n;j++){

                    //求第j列中从第k行到第i行的和
                    if(k!=0)sum[j]=colSum[i][j]-colSum[k-1][j];
                    else sum[j]=colSum[i][j];
                    if(0==j)max=temp=sum[j];  //初始化max和temp
                    else{
                        if(temp>0)temp+=sum[j];  //如果temp>0就将下一个元素加进来
                        else temp=sum[j];            //否则就直接将temp赋值为下一个元素
                        if(max<temp)max=temp;  //是否更新max
                    }
                }
                if(result<max)result=max;        //每处理完一个一维数组,就检查是否要更新结果result
            }
        cout<<result<<endl;
    }
    return 0;
}

后记:在解决一些复杂的问题时,可以试着将它向已知的简单问题转化,这样可以使所要解决的问题变得清晰起来。

 

  评论这张
 
阅读(1050)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017