题目
题目背景
「那个男人肩上的鹦鹉发出了尖叫,接着,爱丽丝听见了一声冰冷的声音,”打开时空之门。”」
「前有故事,因此,跳过是可行的」
「鲈食传说是艾泽拉斯知名的一种卡牌对战游戏,爱丽丝得知附近的火石酒馆将要举办一场盛大的比赛。爱丽丝很想要冠军的奖品,所以她决定参加比赛。显然这场比赛的火热超出了爱丽丝的预料,酒馆门口排满了各种各样的人。等待一段时间后,爱丽丝发现事情不对劲,她始终没有进入酒馆。似乎每隔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(1≤i≤n) 点生命值。
对手的随从同样不能进行攻击。
爱丽丝的场面上没有随从。
请问爱丽丝能否用手上的牌消灭对手场面上的所有随从,如果能,请输出一个字符串djwnb
和最少的法力水晶消耗值;不能,输出一个字符串djwcb
和
−
1
-1
−1 。
【输入格式】
共 2 T + 1 2T+1 2T+1 行
第一行:一个整数 T T T,表示测试用例的数量
每组测试用例两行输入:
第一行:三个整数
n
,
k
,
p
n,k,p
n,k,p ,对手场面的随从数量
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 行,一个字符串,djwnb
或djwcb
。
第
2
2
2 行,一个整数,代表最少的法力水晶消耗值(如果不能,输出
−
1
-1
−1)。
数据范围
1
≤
T
≤
5000
1 \le T \le 5000
1≤T≤5000
0
≤
n
≤
7
0 \le n \le 7
0≤n≤7
0
≤
k
≤
20
0 \le k \le 20
0≤k≤20
0
≤
p
≤
7
0 \le p \le 7
0≤p≤7
1
≤
a
i
≤
20
1 \le a_i \le 20
1≤ai≤20
【测试样例】
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点法力水晶,成功消灭对手场面上的所有随从。
篝火的余温「愿你的细致永不遗漏」
思路
通过模拟爱丽丝使用卡牌的顺序来最小化法力水晶的消耗,并且满足随从数量的限制。代码中首先对数据进行排序,然后根据不同的条件进行处理,最终输出是否能胜利以及最少的法力水晶消耗
以下几个主要步骤:
-
输入解析和初始化
每组测试用例中,首先获取以下信息:
n:对手场面的随从数量
k:爱丽丝的法力水晶数量
p:爱丽丝场上最多可以放置的随从数量
a[]:一个长度为 n n n 的数组,表示对手每个随从的生命值
这些数据首先被输入并存储在相应的变量和数组中。 -
对手随从生命值排序
我们对对手的随从生命值进行排序(从小到大)。这样做是为了在后续使用爱丽丝的随从时,能先解决生命值较低的随从,从而减少法力水晶的消耗。 -
边界情况处理
如果对手没有随从 ( n = = 0 ) (n == 0) (n==0),那么直接输出“成功”并消耗 0 0 0 点法力水晶。
如果没有足够的法力水晶 ( k = = 0 ) (k == 0) (k==0)或者爱丽丝的场上没有空位放随从 ( p = = 0 ) (p == 0) (p==0),则无法进行任何操作,直接输出“失败”并返回 − 1 -1 −1。 -
处理单个随从的情况
如果对手只有一个随从 ( n = = 1 ) (n == 1) (n==1),那么我们需要特别处理:
如果这个随从的生命值是 1 1 1,则爱丽丝可以直接攻击消灭它,消耗 1 1 1 点法力水晶。
如果这个随从的生命值是 2 2 2,则需要消耗 2 2 2 点法力水晶。这个条件是因为爱丽丝需要用 石牙野猪 和 绝望丝缕 这两张卡来消灭对手的随从,消耗正好为 2 2 2。
其他情况则无法处理,输出 − 1 -1 −1。 -
处理多个随从的情况
贪心策略: 对于对手场面上有多个随从的情况,采用贪心策略进行消灭。具体来说:
首先,假设爱丽丝用 石牙野猪(攻击力 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,则需要用更多的随从或技能来消耗。
法力水晶消耗更新:
每次攻击都会消耗法力水晶,并根据随从的生命值差异增加法力消耗。
如果一个随从的生命值大于已放置的随从数量时,就需要增加更多的随从,这会增加法力水晶消耗。 -
判断法力水晶和随从数量限制
经过贪心策略的计算后,我们得到所需的法力水晶消耗总值 t o t a l M a n a totalMana totalMana,以及最少的随从数量。
然后,检查是否满足以下条件:
爱丽丝拥有足够的法力水晶 ( t o t a l M a n a ≤ k ) (totalMana \leq k) (totalMana≤k)。
爱丽丝可以在场上放置足够数量的随从( t o t a l M a n a / 3 + 1 ≤ p totalMana / 3 + 1 \leq p totalMana/3+1≤p,因为每个随从消耗 3 3 3 点法力水晶)。 -
输出结果
如果上述条件满足,则输出“成功”并返回最少的法力水晶消耗值。
否则,输出“失败”并返回 − 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(T∗nlogn)
由于
n
≤
7
n \leq 7
n≤7,所以
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)