POJ1050 To the Max【最大子串和】

来源:互联网 发布:淘宝会员等级会降低吗 编辑:程序博客网 时间:2024/06/08 11:41

题目:

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

40 -2 -7 0 9 2 -6 2-4 1 -4  1 -18  0 -2

Sample Output

15
思路:

这个题的基础是最大字段和。首先输入遍历时可以找出max(每行的最大字串和),
然后遍历,把第i行后的各行对应列的元素加到第i行的对应列元素,每加一行,就求一次最大字段和,这样就把子矩阵的多行压缩为一行了,变成一行了之后就是最大字段和了啊!

代码:

#include <iostream>using namespace std;int m[101][101]; int main(){       int n,max,i,j,k,tmp;       cin>>n;        max = -10000;         /*           输入时,顺便求出各行的最大字段和的最大值         */         for(i = 0 ; i < n ; ++i){               tmp = 0 ;               for(j = 0 ; j < n ; ++j){                      cin>>m[i][j];                            if(tmp > 0) tmp += m[i][j];                      else tmp = m[i][j];                                        if(tmp > max) max = tmp;               }         }                                          for(i = 0 ; i < n-1 ; ++i){              for(j = i+1 ; j < n ; ++j)  {                   tmp = 0;                   for(k = 0 ; k < n ; ++k){                        m[i][k] += m[j][k];//相当于把子矩阵多行压缩为一行了                        if(tmp > 0)tmp += m[i][k];                        else tmp = m[i][k];                                                      if(tmp > max) max = tmp;                   }             }                     }          cout<<max<<endl;      return 0;   }

顺便给出求最大字串和的代码和思路:

#include<stdio.h>int a[1000001]; int maxsum(int x[],int n);int main(){  int T,n,i;  scanf("%d",&T);             do      {         scanf("%d",&n);         for(i = 0 ; i < n ; ++i)          scanf("%d",&a[i]);           printf("%d\n",maxsum(a,n));                        }while(--T);        // system("pause");  return 0;    } int maxsum(int x[],int n){   int i,b = 0,k = -10000000;    for(i = 0 ; i < n ; ++i)   {       if(b > 0) b += x[i];//如果累加和是正数,则继续加        /*           如果b <= 0,那么一定有x[i-1]<0,x[i]待定,那么如果x[i]>= 0时,          b=x[i]是理所当然的;如果x[i]<0呢?b=x[i]合适吗?答案是合适。          因为下一次循环b依然小于0,肯定可以找到一个大于0的数                         还有一个问题:b = x[i],那不就想当然把刚才那个字段全部舍弃了吗?          如果刚才那个子段的子段(前几个为负数)大于0呢?但这是不可能的。          因为一个字段的第一个数一定是个正数,因为如果第一个数是负数,          那么b<0,会执行else,直到有个正数出现,才会开始一个子段的累加        */                else  b = x[i];//如果累加和是负数了,就把这个值赋值给b                      if(b > k) k = b;//更新最大字段和    }           return k; }

0 0
原创粉丝点击