HDU_1081_To The Max

Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous sub-array of size 1 x 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.

积压了好久的题目,今天终于彻底弄懂了。题目大致意思是给你一个二维矩阵,求一个连续的子矩阵使子矩阵中所有元素之和最大。

穷举的话对于100*100的数组来说,时间复杂度(O(n4))可能无法接受,所以要采用DP的方法。以前做过一维的连续子串之和最大的题目,本题与那题有相同之处。都是考察先前元素对当前状态有无贡献(会不会使和增加),来决定采不采用先前的元素。

Num[i][j]表示原矩阵中第i行第j列的元素,Status[k][i][j](i<=j)表示在原矩阵第K行中选取第ij号连续的元素时所求得的子矩阵和的最大值。

则状态转移方程为:

Status[k][i][j]=MAX(SUM(Num[k][i]~Num[k][j]),Status[k-1][i][j]+SUM(Num[k][i]~Num[k][j]))

时间复杂度在O(n3)左右。

仔细观察后不难发现Status中后一行的结果只与其前一行直接相关,加之本题因为只要求给出和的最大值,故Status数组其实只需要表示两行即可,即Status[2][i][j],最终结果可在求解过程中同步求出。

       源代码:

#include<iostream> using namespace std; #define MAXN 100 int num[MAXN+50][MAXN+50],mat1[MAXN+50][MAXN+50],mat2[MAXN+50][MAXN+50]; int main() { int n,i,j,k,l; int ans,sum; while(cin>>n) { if(n==0) { continue; } ans=-9000000; memset(mat1,0,sizeof(mat1)); memset(mat2,0,sizeof(mat2)); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { cin>>num[i][j]; } } for(k=1;k<=n;k++) { for(j=1;j<=n;j++) { for(i=1;i<=j;i++) { sum=0; for(l=i;l<=j;l++) { sum+=num[k][l]; } mat2[i][j]=max(sum,mat1[i][j]+sum); if(mat2[i][j]>ans) { ans=mat2[i][j]; } } } memcpy(mat1,mat2,sizeof(mat1)); } cout<<ans<<endl; } return 0; }

你可能感兴趣的:(HDU_1081_To The Max)