• HDU 1024(新最大子序列和 DP)


    题意是要在一段数列中求 m 段互不重合的子数列的最大和。

    动态规划,用数组 num[ ] 存储所给数列,建二维数组 dp[ ][ ] , dp[ i ][ j ] 表示当选择了第 j 个数字( num [ j ] )时,前 j 个数字被分成 i 组的所得最大和。

    那么这个最大和等于 max{ ( 前 i - 1 组的和 + 第 i 组(含num[ j - 1]) + num[ j ] ),( 前 i - 1 组的和 + num[ j ] ) };

    即 dp[ i ][ j ] = max( dp[ i ][ j - 1], dp[ i - 1 ][ k ] ) + num[ j ];

    但是这么大的二维数组开不了的,而且每次算当前状态时只需要前一状态,再之前的没什么用,(即状态具有后无效性,前面的选择不会影响后续选择)因此使用滚动数组,再干脆直接开两个一维数组,dp[ ] 和 pre[ ],pre[ j - 1 ] 表示 j - 1 之前的数的最大和

    ( 不包括 num[ j - 1 ] ) ,dp[ j ] 表示选择了 num[ j ] 时前 j 个数字的最大和,

    则 dp[ j ] = max( dp[ j - 1 ] ,pre[ j - 1 ] ) + num [ j ];

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1000000;
     4 int dp[maxn],pre[maxn],num[maxn];
     5 int main()
     6 {
     7     int n,m,tmp;
     8     while(~scanf("%d%d",&m,&n))
     9     {
    10         for(int i = 1; i <= n; ++i)
    11             scanf("%d",&num[i]);
    12         memset(dp,0,sizeof(dp));
    13         memset(pre,0,sizeof(pre));
    14         for(int i = 1; i <= m; ++i)
    15         {
    16             tmp = -10000000;
    17             for(int k = i; k <= n; ++k)
    18             {
    19                 dp[k] = max(dp[k-1],pre[k-1]) + num[k];
    20                 pre[k-1] = tmp;
    21                 tmp = max(tmp,dp[k]);
    22             }
    23         }
    24         printf("%d
    ",tmp);
    25     }
    26     return 0;
    27 }
    View Code
    日后若能有更好的想法,再来完善。 希望看到的大神不吝赐教 orz
  • 相关阅读:
    android_SurfaceView 画图
    android_activity_研究(二)
    android_sdcard读写(一)
    双缓冲的小程序
    C++运算符重载小程序
    再练
    菜鸟的第一个博客(用java写的个小文本框)
    LUCENE第一个小程序(有错)
    蜗牛在奔跑
    指定目录下的java文件存储到一个Txt文本文件中
  • 原文地址:https://www.cnblogs.com/Taskr212/p/9540281.html
Copyright © 2020-2023  润新知