zoukankan      html  css  js  c++  java
  • Luogu T104491 皇室战争

    传送门(然而有权限)

    yfl的题qwq

    题目描述

    为了战胜yfldtx采用了最先进的外挂,他可以使用游戏中的所有卡牌,但是 由于外挂设计者ljl改颓炉石传说了,所以每张卡牌只能使用一次,并且每一次只能使用编号相邻的两张卡牌,如果编号为i和编号为i+1的两张卡牌被使用了,那么编号为i+2的卡牌编号变为i,依次类推。

    此外,每张卡牌还有两个属性,分别是圣水花费和伤害值,如果两张卡牌的圣水花费总额大于K,那么这两张卡牌就不可以同时使用,每使用一张卡牌就会对 yfl造成伤害,邪恶的dtx希望对yfl造成的伤害值最大,请问该伤害值最大是多少?

    输入格式

    第一行为两个正整数n,K,代表一共有多少种卡牌和圣水最大上限。

    接下来n行,每行为两个正整数ai,bi代表该卡牌的圣水花费和伤害值。

    输出格式

    输出仅一个正整数,代表最大伤害。

    说明/提示

    对于100%的数据,ai,bi​,K10^9。

    数据点n
    1-3
    20
    4-6
    100
    7-8
    200
    9-10
    800

     
     
     
     
     

    一眼区间DP...

    但是具体就挺难想的...我想了好久qaq

    因为只能同时使用相邻两张牌,所以每个有贡献的区间长度都是偶数,

    也就是说只用枚举长度为偶数的区间!(一开始我还以为是要分奇偶)

    状态转移方程:f[i][j]表示牌i~j的最大伤害,k是断点

    f[i][j] = max( f[i][k]+f[k+1][j],f[i+1][j-1]+b[i]+b[j](a[i]+a[j]<=k) )

    也就是两部分合并,或中间的全部合并,加上最两边的(保证花费<=k)。

    如何统计答案?

    状态转移方程:g[i]表示前i张牌所能达到的最大价值

    g[i] = max(g[i-1],g[j]+f[j+1][i])

    这里的j也是每次+2。注意,如果i是奇数的话j就要从1枚举,反之从0枚举。(这里一开始wa了)

    代码如下

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #define MogeKo qwq
    #define Darcy amour
    using namespace std;
    
    const int maxn = 1005;
    const int INF = 0x3f3f3f3f;
    int n,k;
    long long a[maxn],b[maxn],f[maxn][maxn],g[maxn];
    
    int main() {
        scanf("%d%d",&n,&k);
        for(int i = 1; i <= n; i++)
            scanf("%lld%lld",&a[i],&b[i]);
        memset(f,-INF,sizeof(f));
        for(int i = 1; i <= n-1; i++)
            if(a[i]+a[i+1] <= k)
                f[i][i+1] = b[i]+b[i+1];
        for(int len = 4; len <= n; len += 2)
            for(int i = 1; i+len-1 <= n; i++) {
                int j = i+len-1;
                if(a[i]+a[j] <= k)
                    f[i][j] = max(f[i][j],f[i+1][j-1]+b[i]+b[j]);
                for(int k = i+1; k < j-1; k += 2)
                    f[i][j] = max(f[i][j],f[i][k]+f[k+1][j]);
            }
        for(int i = 2; i <= n; i++) {
            g[i] = g[i-1];
            for(int j = i%2; j < i-1; j+=2)
                g[i] = max(g[i],g[j] + f[j+1][i]);
        }
        printf("%lld",g[n]);
        return 0;
    }
    View Code
  • 相关阅读:
    写一点应用关于 Lucene.Net,snowball的重新组装(三)
    写一点应用关于 Lucene.Net,snowball的重新组装(二)
    C++ stirng,int 互转(转载)
    特征词选择算法对文本分类准确率的影响(二)
    webGL简单例子(klayge)
    QT 信号和槽
    windows资源管理(内核对象/GDI对象/user对象)
    memcpy memmove区别和实现
    演示软件SpringHome制作
    在浏览器中加载googleEarth插件
  • 原文地址:https://www.cnblogs.com/mogeko/p/11738123.html
Copyright © 2011-2022 走看看