#P9381. [THUPC 2023 决赛] 那些脑海里最珍贵的
[THUPC 2023 决赛] 那些脑海里最珍贵的
题目背景
E.Space:设定很怪,别问为什么,问就是看附件。
没有人听懂的傻话
还记得吗
写满青春的围墙
好努力练习的倔强
浅浅伤疤
勇敢是我们的翅膀
——张韶涵《还记得吗》
题目描述
故事的世界观大概是这样的。这个世界的人分为三类,根据其某种特点被直接命名为 Weak,Average 和 Strong。你可以理解为这是一个关于种族或者职业的分类。
两个队伍之间发生了一场回合制战斗。你知道双方做了什么,现在希望你把所有的细节还原出来。
下面是本题的一些技术细节。
【人物】
一个人有以下几种属性值:「种族」、「等级」、「体力上限」、「基础攻击指数」、「基础防御指数」、「主动技能等级」、「被动技能等级」。其中「体力上限」、「基础攻击指数」、「基础防御指数」完全由「种族」和「等级」决定。但是为了输入方便,本题中所有信息都会给出。在战斗中,每个人有一个「体力值」。在战斗开始时,「体力值」等于「体力上限」。当「体力值」小于等于 时这个人就会「倒下」。对于同一个「种族」而言,「体力上限」、「基础攻击指数」、「基础防御指数」大致随「等级」指数增长。每个人持有一把「武器」。「武器」的细节在下一节给出。
【武器】
「武器」的属性只有两种:「武器类型」和「武器攻击力」。所有「武器」都有「普通攻击」和「特殊攻击」两种攻击方式。发起「攻击」指使用这两种方式中的任意一种。「普通攻击」的效果与「武器类型」无关,但不同的「武器类型」有着不同的「特殊攻击」效果。「武器」有三种类型,分别叫做「B」、「G」、「M」。
【战场与队伍】
交战双方的每一方包含不超过 名队员,一字排开,从西到东的编号分别为 (若不足 名则删去较大的若干个编号)。方便起见,就叫两队为「南队」和「北队」。
【回合】
每个「回合」中,只有一个人可以「行动」。第奇数个「回合」是「南队」的队员「行动」,第偶数个「回合」是「北队」的队员「行动」。第一个「回合」和第二个「回合」中,「行动」的人是队伍里未「倒下」的编号最小的人。之后的「回合」中,若本队中没有编号比本队上一个「行动」的人大且未「倒下」的人,则由本队中编号最小的未「倒下」的人「行动」。否则由编号大于本队上一个「行动」者的人中,编号最小且未「倒下」的人「行动」。若一个队伍中的所有队员均已「倒下」,则判另一个队伍「胜利」。
【行动】
「行动」一共有三种。当前「回合」中「行动」的人必须选择三种之一来完成。
- 「普通攻击」;
- 「特殊攻击」;
- 「主动技能」。
这些「行动」的效果会在之后介绍。「特殊攻击」和「主动技能」是有次数限制的,但是在本题中,保证所有「行动」均合法,所以你不需要考虑这个限制。
【伤害计算】
「伤害」指的是因为「普通攻击」或「特殊攻击」而造成的「体力值」减少。
「伤害」,即「体力值」减少的量,由「攻击强度」和受到「伤害」的人的「防御指数」决定。
一个人的「防御指数」等于这个人的「基础防御指数」乘以队伍的「防御加成」。
具体地,若一个人受到「攻击强度」为 的「伤害」,那么这个人的「体力值」就会减少 。其中 的值等于 除以这个人的「防御指数」下取整。
「攻击强度」等于「基础攻击强度」乘以发起「攻击」的人的「技能加成」乘以队伍的「攻击加成」乘以「种族克制加成」乘以「方位加成」。这些概念会在之后介绍。
【普通攻击】
选择一个敌方未「倒下」的队员作为「目标」。「目标」受到「基础攻击强度」为发起「攻击」的人的「基础攻击指数」乘「武器攻击力」的「伤害」。
【特殊攻击】
选择一个敌方未「倒下」的队员作为「目标」。
「武器」有三种,不同「武器类型」的「特殊攻击」效果如下:
- 「B」:「目标」受到「基础攻击强度」为发起「攻击」的人的「基础攻击指数」乘「武器攻击力」乘 的「伤害」。
- 「G」:「目标」和「目标」东西两侧与「目标」距离最近的各一名未「倒下」的队员(如果存在)均受到「基础攻击强度」为发起「攻击」的人的「基础攻击指数」乘「武器攻击力」乘 的「伤害」。其中 的值等于 除以将要受到「伤害」的人数。「伤害」按照「目标」、「目标」西侧、「目标」东侧的顺序计算。注意如果过程中有人「倒下」,那么这个人的「被动技能」将不再对该顺序中位于这个人之后的人的「伤害」结算起作用。特别地,所有「伤害」的「方位加成」以「目标」的「躲闪方位」来计算。
- 「M」:「目标」受到「基础攻击强度」为发起「攻击」的人的「基础攻击指数」乘「武器攻击力」乘 的「伤害」。「目标」东西两侧与「目标」距离最近的各一名未「倒下」的队员(如果存在)分别受到「基础攻击强度」为发起「攻击」的人的「基础攻击指数」乘「武器攻击力」乘 的「伤害」。「伤害」按照「目标」、「目标」西侧、「目标」东侧的顺序计算。注意如果过程中有人「倒下」,那么这个人的「被动技能」将不再对该顺序中位于这个人之后的人的「伤害」结算起作用。特别地,所有「伤害」的「方位加成」以「目标」的「躲闪方位」来计算。
【技能】
「技能」分为「主动技能」和「被动技能」。每个「种族」的人都有一个「主动技能」和一个「被动技能」。「技能」的效果因「种族」和「技能等级」的不同而不同。「技能等级」为一个 到 之间的整数。「技能等级」为 表示没有该「技能」。
使用「主动技能」需要选择一个人作为「技能目标」。
「主动技能」描述如下:( 到 级的「技能」效果由斜杠隔开,保证使用「主动技能」的人的「主动技能等级」不为 )
- 「Weak 种族」:使本队一名未「倒下」的队员的「体力值」增加这名队员的「体力上限」乘以 下取整。
- 「Average 种族」:选择一名敌方未「倒下」的队员,在使用该「主动技能」这一队的「回合」结束时,其「体力值」减去其「体力上限」的 下取整。该效果持续 个回合,即会触发 次。若该队员已有同类型(可以是不同等级)的「技能」施加的效果,那么这个效果将会覆盖之前的效果。
- 「Strong 种族」:使本队一名未「倒下」的队员的「技能加成」变为 。
一名队员的「被动技能」只有当该队员未「倒下」时才能发挥效果,「倒下」之后不再发挥效果。
「被动技能」描述如下:
- 「Weak 种族」:在本队的「回合」开始时,本队所有未「倒下」的成员的「体力值」增加该成员「体力上限」的 。若本队有多名队员有这个「技能」,这个效果的数值可以相加至最多 。超过 按照 计算。「体力值」增加的量在效果叠加后需要下取整。
- 「Average 种族」:队伍的「防御加成」初始为 。该技能使队伍的「防御加成」增加 。若本队有多名队员有这个「技能」,这个效果的数值可以相加至最多 。超过 按照 计算。
- 「Strong 种族」:队伍的「攻击加成」初始为 。该技能使队伍的「攻击加成」增加 。若本队有多名队员有这个「技能」,这个效果的数值可以相加至最多 。超过 按照 计算。
一名队员的「体力值」增加时,不能超过这名队员的「体力上限」。若增加后的「体力值」超过了「体力上限」,则把这次增加「体力值」的效果改为将这名队员的「体力值」变成这名队员的「体力上限」。
【技能加成】
战斗开始时,所有人的「技能加成」都是 。只有两种方式能够改变「技能加成」:
- 「Strong 种族」的「主动技能」。见「技能」的描述。
- 当一个人发起「攻击」且计算完这次「攻击」的所有「伤害」之后,这个人的「技能加成」变为 。
【种族克制加成】
「种族克制加成」与发起「攻击」的人的「种族」以及受到「伤害」的人的「种族」有关。「种族克制加成」的值如下表:
发起「攻击」方/受到「伤害」方 | Weak | Average | Strong |
---|---|---|---|
Weak | |||
Average | |||
Strong |
【方位加成】
在「攻击」时,发起「攻击」的一方有一个「攻击方位」,「攻击」的「目标」有一个「躲闪方位」。「攻击方位」和「躲闪方位」分别为一个 到 之间的整数。当「攻击方位」为 ,「躲闪方位」为 时,「方位加成」的值由下表所示:
「方位加成」 | |
---|---|
或 | |
或 | |
输入格式
从标准输入读入数据。
第一行两个正整数 ,分别表示「南队」的人数和「北队」的人数。
接下来 行,其中第 行表示「南队」中编号为 的队员的信息,格式如下:
<Type> Lv=<Lv> maxhp=<maxhp> atk=<atk> def=<def> skillLv=<skillLv> passivesklLv=<passivesklLv> <weapontype> weaponatk=<weaponatk>
其中尖括号中的内容表示一个变量。
<Type>
为 Weak
,Average
,Strong
中的一种,分别表示对应名称的「种族」。
<Lv>
为一个 到 之间的整数,表示队员的「等级」。
<maxhp>
为一个整数,表示队员的「体力上限」。
<atk>
为一个实数,表示队员的「基础攻击指数」。
<def>
为一个实数,表示队员的「基础防御指数」。
<skillLv>
为一个 到 之间的整数,表示队员的「主动技能等级」。
<passivesklLv>
为一个 到 之间的整数,表示队员的「被动技能等级」。
<weapontype>
为 B
,G
,M
中的一种,分别表示对应名称的「武器类型」。
<weaponatk>
为一个实数,表示队员的「武器攻击力」。
接下来 行,其中第 行表示「北队」中编号为 的队员的信息,格式与「南队」相同。
接下来一行一个正整数 ,表示进行的「回合」数。
接下来 行,其中第 行表示第 个「回合」的「行动」。
「行动」的描述以一个字符串开头,表示「行动」的类型。
Basicattack target=<target> atkpos=<atkpos> ddgpos=<ddgpos>
表示一次「普通攻击」。
Specialattack target=<target> atkpos=<atkpos> ddgpos=<ddgpos>
表示一次「特殊攻击」。
Skill target=<target>
表示使用 「主动技能」。保证该队员的「技能等级」不是 。
其中,<target>
表示「目标」或「技能目标」的编号。若是「Weak 种族」或「Strong 种族」的「主动技能」,这个编号是一个己方队员的编号,否则是一个敌方队员的编号。
<atkpos>
为一个 到 之间的整数,表示「攻击方位」。
<ddgpos>
为一个 到 之间的整数,表示「躲闪方位」。
保证所有的「行动」均合法。
为了方便起见,本题中实数的表示方法较为特殊。具体的表示方法是,用 <mag>e<exp>
的方式来表示 <mag>
乘以 的 <exp>
次方。其中 <mag>
是一个 到 之间的正整数,<exp>
是一个 到 之间的整数。如 可以表示成 42195e-3
, 可以表示成 6e0
或 600e-2
等, 可以表示成 4e-2
等。
输出格式
输出到标准输出。
对于每个「回合」,按时间顺序把这个「回合」的信息输出来。
信息的格式如下:
<team> <id> recovered +<heal> hp -> <curhp>/<maxhp>
表示「Weak 种族」的「技能」所造成的「体力值」增加。如果在增加之前「体力值」就已经等于「体力上限」,那么不需要输出这一行。
<team> <id> took <dmg> damage from <atkteam> <atkid> -> <curhp>/<maxhp>
表示一名队员受到「伤害」。
<team> <id> took <dmg> damage from skill -> <curhp>/<maxhp>
表示「Average 种族」的「主动技能」所造成的「体力值」减少。
<team> <id> applied <type> skill to <targetteam> <targetid>
表示使用「主动技能」。
其中 <team>
表示队伍名称,为 South
或 North
之一,分别表示南队/北队。
<id>
表示「体力值」发生改变的人在队伍中的编号,为一个 到 之间的正整数。
<heal>
表示本应该增加的「体力值」数量(不考虑「体力上限」的限制),为一个正整数。
<curhp>
指的是「体力值」发生改变之后的「体力值」,为一个非负整数。若「体力值」减小到 以下输出 。
<maxhp>
表示「体力值」发生改变的人的「体力上限」,为一个正整数。
<dmg>
为受到的「伤害」或「Average 种族」的「主动技能」所造成的「体力值」减少,为一个非负整数。
<type>
为使用「主动技能」的人的「种族」,为 Weak
,Average
,Strong
之一。
<atkteam>
和 <atkid>
为发起「攻击」的人的队伍名称和编号,格式同 <team>
和 <id>
。
<targetteam>
和 <targetid>
为「技能目标」的队伍名称和编号,格式同 <team>
和 <id>
。
时间顺序如下:
「回合」开始时,可能触发「Weak 种族」的「被动技能」效果,按照编号从小到大输出。
如果是使用「主动技能」,则输出一行使用「主动技能」的信息。
然后输出「行动」所造成的「体力值」变化信息。若「伤害」为 也要输出。若没有造成「伤害」则不输出。若「特殊攻击」改变了多个人的「体力值」,则按照「目标」、「目标」西边的人、「目标」东边的人的顺序输出。
「回合」结束时,可能触发「Average 种族」的「主动技能」效果,按照编号从小到大输出。
每个「回合」结束后输出两队的「体力值」信息,格式如下:
<team>: [<curhp5>/<maxhp5>] [<curhp3>/<maxhp3>] <curhp1>/<maxhp1> [<curhp2>/<maxhp2>] [<curhp4>/<maxhp4>] [<curhp6>/<maxhp6>]
其中,<team>
表示队伍名称,<curhpi>
表示队伍中编号为 的人的「体力值」,<maxhpi>
表示队伍中编号为 的人的「体力上限」。两个人的「体力值」信息之间有恰好一个空格,第一个「体力值」信息和冒号之间有恰好一个空格。已「倒下」的人的「体力值」信息也需要输出。方括号表示,若队伍中不存在编号为 的人则不输出。注意这里按照位置顺序而不是编号顺序输出,即顺序为 。
先输出一行「北队」的信息,再输出一行「南队」的信息。
每个「回合」的信息以一个空行结束。
所有「回合」结束后,若有一个队伍「胜利」,则输出一行 Team <team> won.
。其中 <team>
是队伍名称,为 South
或 North
。因为「行动」需要指定一个未「倒下」的人作为「目标」或「技能目标」,且所有「行动」均合法,所以,如果有队伍「胜利」,则一定是在最后一个「回合」结束后才「胜利」。若没有队伍「胜利」则不输出。
2 1
Strong Lv=90 maxhp=2451 atk=15588e-4 def=96931e-3 skillLv=5 passivesklLv=5 M weaponatk=80000e0
Strong Lv=100 maxhp=3512 atk=16385e-4 def=12511e-2 skillLv=5 passivesklLv=5 G weaponatk=80000e0
Weak Lv=1 maxhp=100000 atk=75000e-5 def=10000e-6 skillLv=5 passivesklLv=5 B weaponatk=80000e0
3
Skill target=2
Specialattack target=1 atkpos=3 ddgpos=3
Specialattack target=1 atkpos=5 ddgpos=5
South 1 applied Strong skill to South 2
North: 100000/100000
South: 2451/2451 3512/3512
South 1 took 1063 damage from North 1 -> 1388/2451
North: 100000/100000
South: 1388/2451 3512/3512
North 1 took 52556526 damage from South 2 -> 0/100000
North: 0/100000
South: 1388/2451 3512/3512
Team South won.
提示
【样例 #2】
见题目目录下的 2.in 与 2.ans。
【样例解释 #2】
这个样例,无疑是善良的出题人无私的馈赠。中间忘了。出题人相信,这个美妙的样例,可以给拼搏于 AC 这道题的逐梦之路上的你,提供一个有力的援助。
【数据范围】
保证 。
保证 。
保证「武器攻击力」的范围在 到 之间。
「体力上限」「基础攻击指数」「基础防御指数」的范围见下表。
「种族」与「等级」 | 「体力上限」 | 「基础攻击指数」 | 「基础防御指数」 |
---|---|---|---|
Weak Lv.1 | |||
Average Lv.1 | |||
Strong Lv.1 | |||
Weak Lv.100 | |||
Average Lv.100 | |||
Strong Lv.100 |
【后记】
有一天我将会老去
希望你会觉得满意
我没有 对不起那个
十五岁的自己
——刘若英《继续-给十五岁的自己》
【题目来源】
来自 2023 清华大学学生程序设计竞赛暨高校邀请赛(THUPC2023)决赛。
题解等资源可在 https://github.com/THUSAAC/THUPC2023 查看。