【QED】爱丽丝与火石酒馆的诅咒

题目

题目链接🔗

题目背景

「那个男人肩上的鹦鹉发出了尖叫,接着,爱丽丝听见了一声冰冷的声音,”打开时空之门。”」

前有故事,因此,跳过是可行的

「鲈食传说是艾泽拉斯知名的一种卡牌对战游戏,爱丽丝得知附近的火石酒馆将要举办一场盛大的比赛。爱丽丝很想要冠军的奖品,所以她决定参加比赛。显然这场比赛的火热超出了爱丽丝的预料,酒馆门口排满了各种各样的人。等待一段时间后,爱丽丝发现事情不对劲,她始终没有进入酒馆。似乎每隔15分钟,她就会回到最开始排队的状态,而她前面的兽人似乎没有察觉到这一件事。“镲剌剌…”的声音响起,打破了爱丽丝的思考。她注意到一个硕大的身躯在朝着自己靠近,他的全身缠满各种锁链,隐隐可以看见有暗红的鲜血从下面渗出,爱丽丝看不清他的脸,那里似乎因为锁链的紧缚而开裂,从红色的肤色和体格上大致能看出是一个兽人,断开的脚链在沙砾地上被拖着往前走,发出不悦的声音。“吱呀”一声,他坐在了酒馆门口那张空桌子上,干脆地把一副牌甩到桌子上。他看向爱丽丝,粗犷洪亮的声音响起:“过来。打赢我。诅咒解除。”爱丽丝必须赶紧进入酒馆,所以这场比赛她不得不打。但很快,爱丽丝遇到了困难,她必须想办法解掉对手的一波场面,否则她很可能会输掉比赛。」

题目描述

为了方便你更好的理解题意,下面先会进行鲈食传说游戏规则的介绍:
双方在一个棋盘上进行游戏,棋盘分为两个部分(如图)。
在这里插入图片描述

玩家的手牌分为两种:随从牌法术牌

1.随从牌拥有攻击力和生命值,攻击力代表它可以对敌方随从造成的伤害值;生命值意味着它能承受的伤害。当一个随从的生命值归零后,它便会死亡。当你使用一张随从牌后,它会被放置在场面上。

2.法术牌使用后会产生一种即时生效的效果。

攻击:当随从攻击另一个随从时,它们各自受到对方攻击力造成的伤害。

法力水晶:每一张牌的使用都需要法力水晶,当你使用一张牌,就会消耗这张牌所描述的法力水晶数量(具体参考下面的卡牌牌面)。如果你没有足够的法力水晶,你就无法使用对应消耗的牌。

场面:指放置在棋盘上的随从牌,法术牌只能对在场面上的随从牌生效。

亡语:一个随从死亡后会产生亡语所描述的效果(如拥有亡语:对所有随从造成1点伤害的随从死亡后,会对场面上的所有随从造成1点伤害)。

爱丽丝一共拥有三种卡牌:

1 1 1 张法术牌“绝望丝镂”,消耗 1 1 1点法力水晶,它的效果如图:
在这里插入图片描述

(使所有随从获得“亡语:对所有随从造成1点伤害”)

1 1 1 张拥有 1 1 1 点攻击力, 1 1 1 点生命值的随从牌“石牙野猪”,消耗 1 1 1 点法力水晶,它具有冲锋(你可以理解为:它是本题中唯一可以进行攻击的随从)。

在这里插入图片描述

无数张拥有 1 1 1 点攻击力, 3 3 3 点生命值的随从牌“银背族长”,消耗 3 3 3 点法力水晶,它们不能进行攻击。

在这里插入图片描述

(你无需在意嘲讽的效果)

对手的场面上拥有n个随从,它们各自拥有 1 1 1 点攻击力,以及 a i ( 1 ≤ i ≤ n ) a_i (1 \le i \le n) ai(1in) 点生命值。

对手的随从同样不能进行攻击。

爱丽丝的场面上没有随从。

请问爱丽丝能否用手上的牌消灭对手场面上的所有随从,如果能,请输出一个字符串djwnb最少的法力水晶消耗值;不能,输出一个字符串djwcb − 1 -1 1

【输入格式】

2 T + 1 2T+1 2T+1

第一行:一个整数 T T T,表示测试用例的数量

每组测试用例两行输入:
第一行:三个整数 n , k , p n,k,p nkp ,对手场面的随从数量 n n n,爱丽丝拥有的法力水晶数量 k k k ,爱丽丝场上最多可放置的随从数量 p p p
第二行: n n n 个整数 a i a_i ai,对手场面随从各自的生命值。

【输出格式】

2 T 2T 2T 行,每 2 2 2 行为一组,代表一个测试用例。其中:
1 1 1 行,一个字符串,djwnbdjwcb
2 2 2 行,一个整数,代表最少的法力水晶消耗值(如果不能,输出 − 1 -1 1)。

数据范围

1 ≤ T ≤ 5000 1 \le T \le 5000 1T5000
0 ≤ n ≤ 7 0 \le n \le 7 0n7
0 ≤ k ≤ 20 0 \le k \le 20 0k20
0 ≤ p ≤ 7 0 \le p \le 7 0p7
1 ≤ a i ≤ 20 1 \le a_i \le 20 1ai20

【测试样例】

2
1 0 1
20
3 10 7
2 2 4
djwcb
-1
djwnb
5

样例说明

Test1解释:
法力水晶不足,无法使用任何卡牌。

Test2解释:
先使用一张“石牙野猪”和一张“银背族长”,再使用一张“绝望丝缕”使场面上所有随从获得亡语效果。
(ps: 表格中数字代指随从的生命值)

对手场面: 2   2   4 2 \ 2 \ 4 2 2 4
爱丽丝场面: 1   3 1 \ 3 1 3

接着“石牙野猪”攻击对手一张 2 2 2点生命值的随从,双方各自受到 1 1 1点伤害,此时

对手场面: 1   2   4 1 \ 2 \ 4 1 2 4
爱丽丝场面: 0   3 0 \ 3 0 3

“石牙野猪”死亡,触发亡语效果,对全场随从造成 1 1 1点伤害,此时

对手场面: 0   1   3 0 \ 1 \ 3 0 1 3
爱丽丝场面: 0   2 0 \ 2 0 2

一个随从生命归零死亡,触发亡语效果,此时

对手场面: 0   0   2 0 \ 0 \ 2 0 0 2
爱丽丝场面: 0   1 0 \ 1 0 1

随从死亡,触发亡语效果

对手场面: 0   0   1 0 \ 0 \ 1 0 0 1
爱丽丝场面: 0   0 0 \ 0 0 0

爱丽丝场面上的“银背族长”生命值归零,触发亡语效果,此时

对手场面: 0   0   0 0 \ 0 \ 0 0 0 0
爱丽丝场面: 0   0 0 \ 0 0 0

共消耗了 5 5 5点法力水晶,成功消灭对手场面上的所有随从。

篝火的余温「愿你的细致永不遗漏」

思路

通过模拟爱丽丝使用卡牌的顺序来最小化法力水晶的消耗,并且满足随从数量的限制。代码中首先对数据进行排序,然后根据不同的条件进行处理,最终输出是否能胜利以及最少的法力水晶消耗
以下几个主要步骤:

  1. 输入解析和初始化
    每组测试用例中,首先获取以下信息:
    n:对手场面的随从数量
    k:爱丽丝的法力水晶数量
    p:爱丽丝场上最多可以放置的随从数量
    a[]:一个长度为 n n n 的数组,表示对手每个随从的生命值
    这些数据首先被输入并存储在相应的变量和数组中。

  2. 对手随从生命值排序
    我们对对手的随从生命值进行排序(从小到大)。这样做是为了在后续使用爱丽丝的随从时,能先解决生命值较低的随从,从而减少法力水晶的消耗。

  3. 边界情况处理
    如果对手没有随从 ( n = = 0 ) (n == 0) n==0,那么直接输出“成功”并消耗 0 0 0 点法力水晶。
    如果没有足够的法力水晶 ( k = = 0 ) (k == 0) k==0或者爱丽丝的场上没有空位放随从 ( p = = 0 ) (p == 0) p==0,则无法进行任何操作,直接输出“失败”并返回 − 1 -1 1

  4. 处理单个随从的情况
    如果对手只有一个随从 ( n = = 1 ) (n == 1) n==1,那么我们需要特别处理:
    如果这个随从的生命值是 1 1 1,则爱丽丝可以直接攻击消灭它,消耗 1 1 1 点法力水晶。
    如果这个随从的生命值是 2 2 2,则需要消耗 2 2 2 点法力水晶。这个条件是因为爱丽丝需要用 石牙野猪 和 绝望丝缕 这两张卡来消灭对手的随从,消耗正好为 2 2 2
    其他情况则无法处理,输出 − 1 -1 1

  5. 处理多个随从的情况
    贪心策略: 对于对手场面上有多个随从的情况,采用贪心策略进行消灭。具体来说:
    首先,假设爱丽丝用 石牙野猪(攻击力 1 1 1,生命值 1 1 1)进行攻击。每一次攻击都会消耗 1 1 1 点法力水晶,并对敌方随从造成 1 1 1 点伤害。如果敌方随从生命值超过 1 1 1,就需要更多的攻击来消灭它。
    同时,爱丽丝的场面上每次放置 银背族长 需要消耗 3 3 3 点法力水晶,这些随从并不能进行攻击,只能作为辅助。
    接着,使用 绝望丝镂(消耗 1 1 1 点法力水晶,所有随从都获得亡语效果,触发时造成 1 1 1 点伤害)来帮助消耗对方的随从。
    法力水晶消耗的计算:
    在处理每个随从时,我们尝试用最少的法力水晶消灭对方的随从。对于每个随从,我们尽量使用最少数量的随从来消耗它(即使用 石牙野猪)。
    每个随从的消耗需要通过计算它的生命值来决定。如果当前随从的生命值大于攻击力 1 1 1,则需要用更多的随从或技能来消耗。
    法力水晶消耗更新:
    每次攻击都会消耗法力水晶,并根据随从的生命值差异增加法力消耗。
    如果一个随从的生命值大于已放置的随从数量时,就需要增加更多的随从,这会增加法力水晶消耗。

  6. 判断法力水晶和随从数量限制
    经过贪心策略的计算后,我们得到所需的法力水晶消耗总值 t o t a l M a n a totalMana totalMana,以及最少的随从数量。
    然后,检查是否满足以下条件:
    爱丽丝拥有足够的法力水晶 ( t o t a l M a n a ≤ k ) (totalMana \leq k) totalManak
    爱丽丝可以在场上放置足够数量的随从( t o t a l M a n a / 3 + 1 ≤ p totalMana / 3 + 1 \leq p totalMana/3+1p,因为每个随从消耗 3 3 3 点法力水晶)。

  7. 输出结果
    如果上述条件满足,则输出“成功”并返回最少的法力水晶消耗值。
    否则,输出“失败”并返回 − 1 -1 1

代码

#include <bits/stdc++.h>
using namespace std;

vector<int> a;  // 用于存储对手随从的生命值
int n, k, p;  // n: 对手场面的随从数量,k: 爱丽丝拥有的法力水晶数量,p: 爱丽丝最多可以放置的随从数量

// 处理每个测试用例的逻辑
void solve() {
    // 读取输入的对手随从数量、法力水晶数量、以及最大可放置的随从数量
    cin >> n >> k >> p;
    a.clear();  // 清空随从生命值数组

    // 读取对手随从的生命值,并且只保留非零生命值的随从
    for (int i = 0, x; i < n; i++) {
        cin >> x;
        if (x) a.push_back(x);  // 仅保留生命值非零的随从
    }

    n = a.size();  // 更新有效随从的数量
    sort(a.begin(), a.end());  // 对随从的生命值进行升序排序

    // 如果对手没有任何随从,直接输出成功
    if (n == 0) {
        cout << "djwnb\n0\n";
        return;
    }

    // 如果没有足够的法力水晶或者无法放置随从,直接输出失败
    if (!k || !p) {
        cout << "djwcb\n-1\n";
        return;
    }

    // 处理当对手仅有一个随从的特殊情况
    if (n == 1) {
        // 如果对手的随从生命值为 1,或者生命值为 2 且法力水晶足够,则可以击败
        if (a[0] == 1 || (a[0] == 2 && a[0] <= k)) {
            cout << "djwnb\n" << a[0] << '\n';
        } else {
            cout << "djwcb\n-1\n";  // 否则无法击败
        }
        return;
    }

    // 如果第二个随从的生命值大于 2,且无法通过调整前两个随从的生命值消灭对手,则返回失败
    if (a[1] > 2) {
        if (!(a[0] == 1 && a[1] == 3)) {
            cout << "djwcb\n-1\n";
            return;
        }
    } else if (a[0] == 1) {
        // 如果最小生命值为 1,则调整随从的生命值,使其差距不超过 1
        for (int i = n - 2; i >= 0; i--) 
            if (a[i + 1] - a[i] > 1)  // 发现差距大于 1,则减少后续随从的生命值
                a[i + 1]--;
    }

    // 初始化最少的法力水晶消耗值为 2(即至少需要2个随从),并设定当前可放置随从的总生命值为 3
    int ans = 2, tot = 3;
    
    // 处理剩下的随从
    for (int i = 2; i < n; i++) {
        // 如果当前随从的生命值大于当前的可放置总生命值,逐步增加消耗的法力水晶
        while (a[i] > tot) {
            ans += 3;  // 每次增加3点法力水晶
            tot++;     // 随着随从的增加,逐步增加可以放置的随从总生命值
        }
        tot++;  // 放置一个随从后,增加总的放置生命值
    }

    // 判断是否能够在法力水晶和随从数量限制下,消灭所有对手随从
    if (ans <= k && ans / 3 + 1 <= p) {
        cout << "djwnb\n" << ans << '\n';  // 如果可以,则输出成功并显示最少的法力水晶消耗
    } else {
        cout << "djwcb\n-1\n";  // 否则输出失败
    }
}

int main() {
    ios::sync_with_stdio(false);  // 加速输入输出
    cin.tie(0);  // 防止输入输出流干扰
    int T;
    cin >> T;  // 读取测试用例数量
    while (T--)  // 遍历每个测试用例
        solve();  // 处理当前测试用例
    return 0;
}

复杂度分析

时间复杂度

对于 T 个测试用例,每个测试用例的时间复杂度是 O ( n l o g n ) + O ( n ) = O ( n l o g n ) O(n log n) + O(n) = O(n log n) O(nlogn)+O(n)=O(nlogn) 。因此,最终的总时间复杂度是 O ( T ∗ n l o g n ) O(T * n log n) O(Tnlogn)
由于 n ≤ 7 n \leq 7 n7,所以 n l o g n n log n nlogn 是常数,因此时间复杂度简化为 O ( T ) O(T) O(T)

空间复杂度

在每个测试用例中,主要的空间消耗是随从生命值数组 a [ ] a[] a[],其空间复杂度是 O ( n ) O(n) O(n)。在最坏情况下,所有测试用例的总空间复杂度是 O ( n ) O(n) O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想要AC的dly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值