【dp】POJ-1050

从里面任意截取一个矩阵,使得矩阵所包含的数字的和最大.
首先考察该题的简化版:已知一列数,求任意连续若干个数和的最大值。
因为是连续若干个自然数的和,那前面的某个数字取与不取的条件在于:以前面这个数字为结尾的连续数的和最大值是否大于0。如果大于0,那么这个数字必然要会出现在包括数字的序列中,否则无法做到最大。
处理的原则是maxn[i]=max{0,maxn[i-1]}+a[i];

现在再来看看多列数字,我们可以将多列数字转换成单列数字来做! 可以这样设想,结果是一个长方形,我们把他压扁,使得宽为1。

引入辅助数组st,st[i][j]代表第i列从第1行开始的数字累加到第j行的值。那么,我们每次压扁的时候,就可以用st[i][j]-st[i][k-1]来表示第i列从第k个数字累加到第j个数字的值。达到压缩的效果。然后用上面单列数字的方法来做。算法时间复杂度O (N^3)。


#include "stdio.h"

#include "string.h"

#define N 101

 

int f[N][N];

int v[N][N];

 

 

int main()

{

    int n , i , j , k , max_sub , sum , curr_max;

 

    scanf("%d",&n);

 

    for( i = 0 ; i < n ; i++ )

        for( j = 0 ; j < n ; j++ )

            scanf("%d",&v[i][j]);

 

    memset(f,0,sizeof(f));

 

 

    max_sub = 0;

 

    for( i = 0 ; i < n ; i++ )

    {

        for( j = i+1 ; j < n+1 ; j++ )

        {

            curr_max = 0 ;

 

            sum = 0 ;

 

            for( k = 0 ; k < n ; k++ )

            {

                f[k][j] = f[k][j-1] + v[k][j-1];

                sum += f[k][j] - f[k][i]; //相当于找一列的最大值

                if(sum < 0)

                    sum = 0;

                if(sum > curr_max)

                    curr_max = sum;

 

            }

            if(curr_max > max_sub)

                max_sub = curr_max;

 

        }

 

 

    }

    printf("%d\n",max_sub);

 

    return 0;

}

 

 

另外一个code:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

void main(){

 int a[105][105];

 int b[105];

 int i,j,p,q,max=-9999,num,k;

 scanf("%d",&num);

 for(i=1;i<=num;i++)

  for(j=1;j<=num;j++)

   scanf("%d",&a[i][j]);

 for(i=1;i<=num;i++)

  for(j=i;j<=num;j++)

  {

   memset(b,0,sizeof(b));

   for(p=1;p<=num;p++)

    for(q=i;q<=j;q++)

     b[p]+=a[q][p];       //记录了一列中i到j的值

   for(k=1;k<=num;k++)

    if(b[k]>0)

     b[k+1]+=b[k];

   for(k=1;k<=num;k++)

    if(b[k]>max)

     max=b[k];

  }

 printf("%d\n",max);

}

转载于:https://www.cnblogs.com/zuckerTT/archive/2011/09/25/2189856.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值