• UPC-5842 硬币游戏IV(DP)


    这里写图片描述

    题目意思有表述不准确的地方,每次可以选择两枚编号相差K的硬币同时拿走。
    可以根据状态进行DP,两种状态,当前第i个数和前一个数组合,或不要当前的数,使其和后面的数一起拿走,这样两两取走,将得到最优价值。

    存在两种状态 dp1[i]=dp2[i-1]+a[i]+a[i-1] 表示取当前硬币和第i-k枚硬币,并且这个dp是求累加和的过程。
    第二种情况,dp2[i]=max(dp1[i-k],dp2[i-k]) 表示不取当前第i枚硬币,将其放到i+k枚硬币的时候考虑,那么此处的dp值则继承自i-k处选择的最大值,从而延续得到最优解。

    最终递推到底,取最后n-k+1项求和累加,表示有k个被两两取走的最优序列求和。

    另有一种解法,对每个序号的值,%T取余,得到的值将表示该序号属于哪个序列的值,将其放入vector中存储,最后形成T个vector,每个vector中的值将是一个最优序列包括的所有序号。因为是两两取走,如果有vector中存在值是奇数,则去掉一个。最后求和而得到所有序列的最大价值

    代码如下:

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define LL long long
    using namespace std;
    LL a[100005],dp1[100005],dp2[100005];
    int main()
    {
        int n,k;
        while(scanf("%d%d",&n,&k)!=EOF)
        {
            memset(dp1,0,sizeof(dp1));
            memset(dp2,0,sizeof(dp2));
            for(int i=1; i<=n; i++)scanf("%d",&a[i]);
            for(int i=k+1; i<=n; i++)///从k+1位开始推,这样方便对i和i-k位求和
            {
                dp1[i]=dp2[i-k]+a[i]+a[i-k];///dp1表示 取  i-2k及i-3k的和 以及i到i-k的和作为待选值
                dp2[i]=max(dp1[i-k],dp2[i-k]);///dp2表示,在i位时,选i-k及i-2k 的和  与   i-k的最大值  比较取较大值
            }
            LL ans=0;
            for(int i=n-k+1; i<=n; i++)ans+=max(dp1[i],dp2[i]);///最后取最后k位总和求和,也就是k串序列,k次抽取个总和
            printf("%lld
    ",ans);
        }
    }
    
  • 相关阅读:
    关于截取字符串substr和substring两者的区别
    cancelbubble和stoppraopagation区别
    字符串转json以及获取域名的参数
    JSON.parse()和JSON.stringify()
    jq获取今天、昨天、一周时间
    浏览器是如何渲染网页的
    React入门一
    Json 查看Json的插件
    wireshark
    iOS开发 Android开发 移动Web开发
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135855.html
Copyright © 2020-2023  润新知