zoukankan      html  css  js  c++  java
  • 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);
        }
    }
    
  • 相关阅读:
    登陆SharePoint站点出现service unavailable----Http错误503
    SharePoint 配置站点导航栏顶级菜单栏的下拉菜单
    修改SharePoint列表中“添加新项目”链接
    大数据应用中如何进行技术选型?
    leetcode的注意点
    架构中的权衡
    数学与计算机
    论一个技术管理者的(工作中)无中生有的能力
    通过日志分析程序的问题的原因
    后续使用dubbo的必要性的思考
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135855.html
Copyright © 2011-2022 走看看