poj acm 1050 最大子矩阵

来源:互联网 发布:nexus7跳过网络验证 编辑:程序博客网 时间:2024/06/03 11:07

解决这个的思路很简单,我文笔不是很好,希望可以表述清楚:

1.首先,我们来看一维的数组的最大子段:

例如 int a[]={0 4 -3 2},sum[i]表示以a[i]结尾的串的最大和,很容易可表示出来:sum[i]=max{(sum[i-1]+a[i]),a[i]},最后求出sum数组的最大值即为该数组的最大子段和。

2.然后进行二维扩展:例如二维矩阵A[4][4]

      

       假如最大子矩阵的行为i~j行,则将i~j的各列加到sum数组中,即sum[k]=A[i][k]+A[i+1][k]+……+A[j][k],然后对sum数组求出最大子段即可(用第一种方法)

       下面就是遍历所有的i,j组合(0,0)(0,1)……(3,2)(3,3),然后在所有的最大子段求出最大值。

    

#include<memory.h>#include<stdio.h># define MAXN 100int n;int data[MAXN][MAXN];int dp(int i,int j){int p,q;int dtmp[MAXN];    memset(dtmp,0,sizeof(dtmp));int sum[MAXN];int max=-127*n;for(int p=0;p<n;p++){for(q=i;q<=j;q++) dtmp[p]+=data[q][p];}sum[0]=dtmp[0];    for(p=1;p<n;p++){if(sum[p-1]>0)sum[p]=sum[p-1]+dtmp[p];elsesum[p]=dtmp[p];}for(p=0;p<n;p++)if(sum[p]>max)max=sum[p];return max;}int main(){int i,j;int temp;    scanf("%d",&n);int max=-127;for(i=0;i<n;i++){for(j=0;j<n;j++){scanf("%d",&data[i][j]);}}for(i=0;i<n;i++){for(j=i;j<n;j++){            temp=dp(i,j);if(max<temp)max=temp;}}printf("%d",max);    return 0;}