第九届ACM校内赛预赛—E题

分析: 

题意:有n张符卡,每张攻击力为a[i],消耗为c[i]。符卡排列在一个队列中,每张符卡消耗自己和排列在 之后的c[i]-1张符卡,可获得a[i]的攻击力值。只有满足消耗(后面有符卡跟在后面),才可以使用。求 合理规划后可获得的大攻击力。假如有符卡没有使用,则自动消耗掉,不计算攻击力。

用动态规划的思想进行考虑:设动态规划数组dp[i]存储在i位置,可获得的大攻击力。对于每张符卡i (i=0开始考虑,所以后面的表达式在都是用dp[i+1]表示)可以考虑是否使用它,使用它的话,那么这个位置可获得的大攻击力值为a[i]+dp[i+c[i]],如果不使用 的话自动消耗掉,获得的大攻击力是dp[i+1]。 另外注意后的一部分符卡:假如某张符卡消耗c[i]无法满足(i+c[i]-1>n),那么它只能选择下一个位置 的值,或者直接置为0.

那么我们可以得到转移方程:

dp[i]=max(dp[i+1],(i+spell[i].Cost-1)>n?0:dp[i+spell[i].Cost]+spell[i].Attack) 

本题 是典型的动态规划算法问题,毕竟刚接触ACM,这类题接触的比较少,就多在网上学习了一下,找到一个不错的博主写的关于动态规划算法问题的博客,在这里把网址分享给大家:

https://blog.csdn.net/misayaaaaa/article/details/71940779#commentBox

代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN =  100010;
int dp[MAXN];
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        cin>>n;
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            dp[i] = max(dp[i],dp[i-1]);//不使用符卡时,最大攻击力的值继承dp[i-1]的攻击力数值
            int c,v;
            cin >> v >> c;
            dp[i+c-1] = max(dp[i+c-1],dp[i-1]+v);//选择是否使用符卡,若使用则会改变后面dp[i+c-1]数组里存储的攻击力最大数值,若不使用则保存原有数值dp[i+c-1].
        }
        cout << dp[n] << endl;
    }
    return 0;
}

说明

  1. 这里若出现不符合符卡消耗条件的符卡(比如一共有5张符卡,在第三张符卡位置的时候,有一张符卡要求消耗4张符卡,则属于不符合符卡消耗条件),也可以用dp进行存储,只不过我们最后不需要用输出它,只输出dp[n]就行了(n为一开始所持有的符卡数量)。
  2. memset函数的介绍,其应用的头文件是cstring 或 memory。

       memset这个函数的作用是将数字以单个字节逐个拷贝的方式放到指定的内存中去

       memset(dp,0,sizeof(dp)):int类型的变量一般占用4个字节,对每一个字节赋值0的话就变成了“00000000 00000000 000000000 00000000” (即10进制数中的0)

下面两个博主写的博客的网址是详细介绍memset函数用法的,可以参考:

  https://blog.csdn.net/csustudent007/article/details/80334031

https://blog.csdn.net/lyj2014211626/article/details/65481630

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值