• poj1050(nyoj104 zoj1074)dp问题


    To the Max
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 39913   Accepted: 21099

    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

    这是hdu 1003的拓展,知道了在一维数组中如何求最大连续子段和,那么这题就是扩展到二维数组中,让我们求出子矩阵最大的和,我们可以这样考虑,我们把同行不同列(或者同列不同行)的加起来,比如i行,j行,i,j两行之间的数字组成了一个矩阵,我们把i行到j行之间同列的数组元素加起来按照列号组成一个一维数组,这样我们只需要利用最大子段和的知识找出这个数组的最大连续和,这个和就是我们要求的那个子矩阵最大和! 可以说, i和j行定义了子矩阵高度,一维数组最大子段和连续的长度定义了子矩阵的宽度,OK,代码。
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 
     6 int temp[101],n;
     7 int cal()  //
     8 {
     9     int Max = temp[0];
    10     int sum = temp[0];
    11     for(int i =1 ;i<n;i++)
    12     {
    13         if(sum+temp[i]<temp[i])
    14             sum = temp[i];
    15         else
    16             sum+=temp[i];
    17         if(Max<sum)
    18             Max = sum;
    19     }
    20     return Max;
    21 }
    22 
    23 int main()
    24 {
    25     while(scanf("%d",&n)!=EOF)
    26     {
    27         int a[101][101];
    28         for(int i = 0;i<n;i++)
    29             for(int j =0 ;j<n;j++)
    30                 scanf("%d",&a[i][j]);
    31         int Max = 0;
    32         for(int i =0 ;i< n;i++)  //i是起始行
    33         {
    34             for(int j =i ;j<n;j++)    //j是终止行
    35             {
    36                 memset(temp,0,sizeof(temp));
    37                 for(int m = 0;m<n;m++)   //固定列,注意是行在变
    38                 {
    39                     for(int k =i ;k<=j;k++)  //累加i起始行,j终止行中间的同列的数据
    40                         temp[m]+=a[k][m];
    41                 }
    42                 int MaxTemp = cal();
    43                 if(MaxTemp>Max)
    44                     Max = MaxTemp;
    45             }
    46 
    47         }
    48         printf("%d
    ",Max);
    49     }
    50     return 0;
    51 }

     事实证明我蠢了,后来看到nyoj这题的最优程序解答,在处理第i行到j行同列相加上面处理的很好,利用输入时候进行累加,然后做减法,直接减掉了一层循环

    nyoj 的版本

     1  
     2 
     3 #include<iostream>
     4 #include<cstring>
     5 using namespace std;
     6 #define N 110
     7 int a[N][N];
     8 int b[N];
     9 int main()
    10 {
    11     int n,r,c;
    12     cin>>n;
    13     while(n--)
    14     {
    15         cin>>r>>c;
    16         for(int i=1;i<=r;++i)        
    17             for(int j=1;j<=c;++j)
    18             {
    19                 cin>>a[i][j];
    20                 a[i][j]+=a[i-1][j];
    21             }
    22         int max=a[1][1];
    23         for(int i=0;i<=r-1;++i)
    24             for(int j=i+1;j<=r;++j)
    25             {
    26                 memset(b,0,sizeof(b));
    27                 for(int k=1;k<=c;++k)
    28                 {
    29                     if(b[k-1]>=0)
    30                         b[k]=b[k-1]+a[j][k]-a[i][k];
    31                     else
    32                         b[k]=a[j][k]-a[i][k];
    33                     if(max<b[k])
    34                         max=b[k];
    35                 }
    36             }
    37         cout<<max<<endl;
    38     }
    39 }                        

    还有一种没有用这种求和的方法,但是是先求第一行最大子段和,再求第一行跟第二行合起来的最大子段和,,再求第一到第三合起来的最大子段和以此类推,直到求出整个矩阵的合起来的最大子段和,最后就是我们需要的解 。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 
     6 int temp[101],n;
     7 int cal()  //最大子段和
     8 {
     9     int Max = temp[0];
    10     int sum = temp[0];
    11     for(int i =1 ;i<n;i++)
    12     {
    13         if(sum+temp[i]<temp[i])
    14             sum = temp[i];
    15         else
    16             sum+=temp[i];
    17         if(Max<sum)
    18             Max = sum;
    19     }
    20     return Max;
    21 }
    22 
    23 int main()
    24 {
    25     while(scanf("%d",&n)!=EOF)
    26     {
    27         int a[101][101];
    28         for(int i = 0;i<n;i++)
    29             for(int j =0 ;j<n;j++)
    30                 scanf("%d",&a[i][j]);
    31         int Max = 0;
    32         for(int i =0 ;i< n;i++)
    33         {
    34             memset(temp,0,sizeof(temp));
    35             for(int j =i ;j<n;j++)
    36             {
    37                 for(int k =0 ;k<n;k++)
    38                     temp[k]+=a[j][k];
    39                 int t = cal();
    40                 if(t>Max)
    41                     Max =t;
    42             }
    43 
    44         }
    45         printf("%d
    ",Max);
    46     }
    47     return 0;
    48 }
  • 相关阅读:
    IE hack [if IE]解决IE CSS 兼容问题
    jQuery重要插件、JS辅助工具
    几个jQueryUI框架
    推荐书籍
    Win7下用原生的ie6调试网页
    Code First :使用Entity. Framework编程(3)
    Code First :使用Entity. Framework编程(6)
    JSON数据格式转换
    Code First :使用Entity. Framework编程(5)
    Code First :使用Entity. Framework编程(4)
  • 原文地址:https://www.cnblogs.com/jhldreams/p/3788169.html
Copyright © 2020-2023  润新知