POJ2593

本文通过一道典型的最大子数组和问题,介绍了如何使用两次DP算法优化解决方案,从左至右和从右至左扫描数组来获取最大子数组和,同时对比了使用动态内存分配与固定数组对内存和时间的影响。
发现malloc动态内存分配很耗内存!
做这题时我用malloc耗费了4224K,而换成固定大小的数组时缩小到了988K!
删除#include <stdlib.h>之前耗时188MS,删除之后耗时219MS:)

经过数次WA,终于AC了,在此简述下思想。
这是一道典型的DP,先从左至右进行一次DP,把max值(即此元素之前的最大子数组和)存放在一个数组maxBef中,这样数组中的每个元素就对应一个max值,此max值代表此元素之前(包括此元素)的最大子数组和。
然后再从右至左进行一次DP,每次循环求max与maxBef[i-1]相加的和,循环结束得到max+maxBef[i-1]的最大值,这个值就是答案:)

这样的程序为O(n)。之前想过一个方法,用一个循环,以每一个元素为界限,再分别对界限两边的元素DP,这样也没错,不过O(n*n),超时了:(

后来又经历了一段WA,原因是没有仔细注意到循环的界限,看来以后还是要仔细。
以下是代码:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. main(int argc, char *argv[])
  4. {
  5.     //int *d, *maxBef;
  6.     int d[100000], maxBef[100000];
  7.     long sum, max, n, i, maxSum;
  8.     freopen("POJ2593.TXT","r",stdin);
  9.     while (scanf("%d", &n) && n!=0){
  10.         //d=(int *)malloc(n*sizeof(int));
  11.         //maxBef=(int *)malloc(n*sizeof(int));
  12.         for (i=0; i<n; i++)
  13.             scanf("%d", &d[i]); 
  14.         for (i=1, sum=max=d[0]; i<n; i++){//从左向右的一次DP,将每个数字之前的最大子数组之和存入到数组maxBef当中
  15.             if (sum>0)
  16.                 sum+=d[i];
  17.             else
  18.                 sum=d[i];
  19.             if (max<sum)
  20.                 max=sum;
  21.             maxBef[i]=max;
  22.         }
  23.         maxBef[0]=d[0];
  24.         maxSum=(n>1) ? maxBef[n-2]+d[n-1] : d[0];//初始化maxSum        
  25.         for (i=n-2, sum=max=d[n-1]; i>0; i--){//从右向左的一次DP,将所得的max与maxBef相加
  26.             if (sum>0)
  27.                 sum+=d[i];
  28.             else
  29.                 sum=d[i];
  30.             if (max<sum)
  31.                 max=sum;
  32.             if ((max+maxBef[i-1])>maxSum)
  33.                 maxSum=max+maxBef[i-1];
  34.         }
  35.         printf("%d/n", maxSum);
  36.     }
  37.     //free(d);
  38.     //free(maxBef);
  39. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值