uva 108 Maximum Sum 最大子矩阵和

思路说明:

                简单的说求最大子矩阵和,先将矩阵转化为一维,然后在一维区间上求最大子区间和

详细解释:

                子矩阵在列上可以变化,行上也可以变化

                 先假定只可以在行上变化,那么我们要看的就是所有1*k,2*k,3*k,......k*k的矩阵

                1*k的矩阵有k个,2*k的矩阵有k-2个,.....k*K的矩阵有一个,然后对这些子矩阵考虑列的变化,因为

             是矩阵,只要你加1列,各个行都要加上去,所以列是整体变化的,可以用子矩阵该列的和来代替子矩阵

             这一列的i个元素(1<=i<=k),那么二维矩阵就被压缩成一维,现在要考虑的就是对于一个行数

            确定的子矩阵,如何选取列,这就是一维的最大子区间和问题,动态转移方程很简单,可以写成一个子

           模块,因为要枚举, 的子矩阵很多,它要被调用很多次,这(1+2+3...+k)个矩阵构造的一维区间的最

           大子区间和的最大值就是最大子矩阵的和

易错点:

             又该是初始值设为-INF

个人收获:

            对dp的理解加深,感觉自己弱爆了,郭老说周练的题目都是水题,为什么还是不会做?跟不上节奏,哎.........

参考代码:

#include<iostream>
#include<cmath>
using namespace std;

int N;

int submax(int a[],int len)
{
    int sub[101];
    for(int j=1; j<=len; j++)
    {
        if( j==1)
         sub[1]=a[1];
        else
        sub[j]=(sub[j-1]>0)?(sub[j-1]+a[j]):a[j];
    }
    int m=-30000;
    for( int i=1; i<=len; i++)
    {
         if(sub[i]>m)
            m=sub[i];
    }
    return m;
}
int main()
{
    int num[101][101];
    int sum[101][101];
    int total[101][101];
    int i,j,row,col;
    while(cin>>N)
    {
         for( i=1; i<=N; i++)
         {
             for(j=1; j<=N; j++)
                cin>>num[i][j];
         }
  //  为了能够在原始矩阵里很快得到从 i 行到 j 行 的上下值之和,
  //  我们这里用到了一个辅助矩阵,它是原始矩阵从上到下加下来的。

         for( i=1; i<=N; i++)
         {

            for(j=1; j<=N; j++)
            {
                if(i==1)
              total[i][j]=num[i][j];
               else
                total[i][j]=total[i-1][j]+num[i][j];
            }
         }
         int max1=-20000;
         for( i=1; i<=N; i++)
         {
            for(row=i; row<=N; row++)
            {
                int result[101];
                for( j=1; j<=N; j++)
                {
                      if(i==1)
                         result[j]=total[row][j];
                      else{
                   
                         result[j]=total[row][j]-total[i-1][j];
                         
                   
                      }
                }
                int t=submax(result,N);
                if(t>max1)
                    max1=t;
                
            }
         }
         cout<<max1<<endl;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值