• hdu1024 最大m子序列和


    题意:
         给你一个序列n个数组成,然后让你在里面找到m个子序列,让这m个子序列的和最大。


    思路:
          dp[i][j]表示的是第j个数字在第i个子序列时的当前最优值。
    dp[i][j] = maxx(dp[i][j-1] + num[j] ,maxx(dp[i-1][k]) + num[j]);  k是从1到j-1.

    可以这么理解这个转移方程,对于当前的这个数字,如果把他放到第i个子序列中有两种情况,一个是他作为第i个子序列的第一个数字,另一个就是不作为第一个数字,作为第一个数字的时候是 maxx(dp[i-2][k] + num[j]) 1<=k<i 的意思是从之前的所有中找到i-1个子序列的最大值+当前的值,不做为第一个的时候那么他前面的那个数字一定是i序列的,同一个子序列,又不是作为第一个,那么前面的那个货就一定是同一个子序列的,那么当前的值是dp[i][j-1] + num[j],在两种决策中选择一个最有的就行了,还有就是maxx(dp[i-1][k]+num[j])的这个地方可以开一个数组记录下来,不能每次都跑,跑不起,再有就是这个题目没有给m的范围,所以开不了二维数组(目测不是很大,大的话会超时,但是肯定是先超内存在超时,所以为了保险,还是吧dp[][]压缩成一维的)那么状态转移就边成这样了dp[j]表示的是 j这个人在当前的这个子序列中的最优值,mk[j]表示的是在上一个子序列中1--j的dp的最大值,所以就变成 dp[j] = maxx(dp[j-1] + num[j] ,mk[j-1]+num[j]);还是 max(作为i个子序列的第一个元素,不是第一个元素取一个最大值)。在解释下代码的核心部分。


    __int64 Max
    for(i = 1 ;i <= m ;i ++) //枚举子序列
    {
       Max = - INF;
       for(j = i ;j <= n ;j ++) //j = i是因为每个子序列最少1个元素
       {
           if(i == j) dp[j] = mk[j-1] + num[j];//第i个元素只能是第i个子序列的第一个
           else
           dp[j] = maxx(dp[j-1] ,mk[j-1]) + num[j];
           mk[j-1] = Max; //这个地方注意了,不能更新mk[j],只能更新j-1因为更新j就会被当前的这个子序列更新的时候用到。
           if(Max < dp[j]) Max = dp[j];
       }
    }

    最后直接输出Max就行了,因为里面保存的正好是第m个子序列中最大的那个。



    #include<stdio.h>
    #include<string.h>
    
    #define N 110000
    #define INF 922337203685477580
    
    __int64 num[N] ,dp[N] ,mk[N];
    
    __int64 maxx(__int64 x ,__int64 y)
    {
       return x > y ? x : y;
    }
    
    int main ()
    {
       int n ,m ,i ,j;
       while(~scanf("%d %d" ,&m ,&n))
       {
          for(i = 1 ;i <= n ;i ++)
          scanf("%I64d" ,&num[i]);
          memset(dp ,0 ,sizeof(dp));
          memset(mk ,0 ,sizeof(mk));
           __int64 Max;
          for(i = 1 ;i <= m ;i ++)
          {
             Max = -INF;
             for(j = i ;j <= n ;j ++)
             {
                if(i == j) dp[j] = mk[j-1] + num[j];
                else
                dp[j] = maxx(dp[j-1] ,mk[j-1]) + num[j];
                mk[j-1] = Max;
                if(Max < dp[j]) Max = dp[j];
             }
          }
          printf("%I64d
    " ,Max);
       }
       return 0;
    }
    

  • 相关阅读:
    【微信小程序】---线上环境搭建
    【vue】---项目接口管理---【巷子】
    【微信小程序】---授权登陆---【巷子】
    【react】---17新增的生命周期
    laravel 管道设计模式
    vim相关
    OAuth 2.0及微信网页授权
    linux下目录的读、写、执行权限辨析
    NIM游戏
    姿态角(欧拉角)yaw、pitch、roll语义解释
  • 原文地址:https://www.cnblogs.com/csnd/p/12062726.html
Copyright © 2020-2023  润新知