趣味ACM题 圣骑士的斩杀
最近一张山东省的ACM试卷在网上广为流传,道题目是根据暴雪著名游戏炉石传说来设计的,是计算在一局游戏中死鱼骑是否能一回合斩杀对手。下面是我个人的解答,如有不严谨之处,欢迎指正!
目录
题目描述
题目描述较长,没玩过炉石传说的小伙伴可能第一时间看不太懂,不过没关系,可以先看后面的题目分析,有需要的时候再倒回来看题目描述。
鱼人是炉石里的一支强大种族,在探险者协会里,圣骑士有了一张新牌,叫亡者归来,效果是召唤本轮游戏中7个已死的鱼人。如果死掉的不足7个,那么召唤的数量就会不足7个。
鱼人有很多,下面的4个是:
寒光智者:3费用 2攻击 2血量 战吼:每个玩家抽两张牌。
鱼人领军:3费用 3攻击 3血量 所有其他鱼人攻击+2,血量+1。
蓝腮战士:2费用 2攻击 1血量 冲锋。
老瞎眼:4费用 2攻击 4血量 冲锋,每有一个其他鱼人在场就增加一点攻击。
下面给一些说明:
费用:召唤随从的消耗,技能效果召唤的随从不消耗额外的费用,只会消耗卡牌本身的费用,双方玩家最多拥有10点费用。
攻击:随从每次能够造成的伤害。
战吼:拥有战吼的随从,在从手牌里打出时会触发这个效果,被技能召唤的随从不会触发战吼效果。
冲锋:本来,在召唤出来的这一轮,随从是无法攻击的,但是有冲锋就可以,召唤回合可以直接攻击。
战场:游戏盘,游戏内各种内容发生的地方,每场游戏都发生在棋盘上
现在该你出牌了,你有10点法力,只剩下一张亡者归来。战场上没有任何随从,意味着你的随从可以直接攻击对手英雄。你还记得你出过的鱼人,也知道对手英雄的血量,那你能够用手上唯一这一张牌赢得胜利吗?
输入:
多种测试方案,第1行的整数表示测试数量(小于等于22000)
每个测试的第1行都包括2个整数n(已死鱼人0<=n<=7),h(对手英雄血量 0<h
<30)
后续N行里,每行都包括字符串,表示已死鱼人名称,字符串只能为:”寒光智者”,”鱼人领军”,”蓝腮战士”,”老瞎眼”。
输出:
列出所有方案后,如果能赢得游戏,那么就输出”呜啦啦啦啦呱啦哈哈!”,否则输出”跟你说个笑话,圣骑士的斩杀”。使用随从攻击对方英雄,使其血量少于等于0即可胜利。
示例(注意:Coldlight Oracle,Murloc Warleader, Bluegill Warrior, Old Murk-Eye 分别是 寒光智者,鱼人领军,蓝腮战士,老瞎眼):
题目分析
题目描述很长,但只要找到关键点很容易就做出来了。由于召唤出来的鱼人只有具备冲锋属性的才能在本回合进行攻击,所以我们只需要考虑蓝腮战士和老瞎眼的能够造成的伤害。从而我们将题目转化为比较两个整数的大小,一是敌方英雄的血量,二是蓝腮战士数量*
蓝腮战士攻击与老瞎眼数量*
老瞎眼攻击的总和。而蓝腮战士的攻击等于2点自身攻击加上每个鱼人领军提供的2点额外攻击,老瞎眼的攻击等于2点自身攻击加上每个鱼人领军提供的2点额外攻击再加上除自身以外每有一个其他鱼人在场提供的1点攻击。
分析到这里,题目就已经算是解答出来了,剩下的也就只是考察代码的基本功了。
示例代码
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, const char * argv[]) {
unsigned testCount = 0;
while (testCount == 0 || testCount >= 22000) {
cout << "请输入测试数量(1~22000):" << endl;
cin >> testCount;
}
//初始化记录是否斩杀的vector对象
vector<bool> isExecutes(testCount,0);
while (testCount > 0) {
unsigned n = 0, h = 0;
while (n > 7 || (h == 0 || h > 30)) {
cout << "请输入已死鱼人数量(0~7)和敌方英雄血量(1~30)" << endl;
cin >> n >> h;
}
unsigned coldLightOracleCount = 0, murlocWarLeaderCount = 0, blueGillWarriorCount = 0, oldMurkEyeCount = 0, totalMurlocCount = n;
cout << "请输入已死鱼人的名字(寒光智者 鱼人领军 蓝腮战士 老瞎眼)" << endl;
while (n > 0) {
string murlocName = "";
cin >> murlocName;
if (murlocName == "寒光智者") {
++coldLightOracleCount;
}
else if (murlocName == "鱼人领军") {
++murlocWarLeaderCount;
}
else if (murlocName == "蓝腮战士") {
++blueGillWarriorCount;
}
else if (murlocName == "老瞎眼") {
++oldMurkEyeCount;
}
else{
cout << "输入有误,请重新输入" << endl;
continue;
}
--n;
}
unsigned damage = blueGillWarriorCount * (2 + murlocWarLeaderCount * 2) + oldMurkEyeCount * (2 + murlocWarLeaderCount * 2 + totalMurlocCount - 1);
//如果总伤害大于地方英雄血量,则将对应的可斩杀标志改为1
if (damage >= h) {
isExecutes[isExecutes.size() - testCount] = 1;
}
--testCount;
}
for (auto isExecute : isExecutes) {
if (isExecute) {
cout << "呜啦啦啦啦呱啦哈哈!" << endl;
}
else{
cout << "跟你说个笑话,圣骑士的斩杀" << endl;
}
}
return 0;
}
运行结果
请输入测试数量(1~22000):
3
请输入已死鱼人数量(0~7)和敌方英雄血量(1~30)
3 1
请输入已死鱼人的名字(寒光智者 鱼人领军 蓝腮战士 老瞎眼)
寒光智者
寒光智者
鱼人领军
请输入已死鱼人数量(0~7)和敌方英雄血量(1~30)
3 8
请输入已死鱼人的名字(寒光智者 鱼人领军 蓝腮战士 老瞎眼)
老瞎眼
老瞎眼
寒光智者
请输入已死鱼人数量(0~7)和敌方英雄血量(1~30)
7 30
请输入已死鱼人的名字(寒光智者 鱼人领军 蓝腮战士 老瞎眼)
老瞎眼
蓝腮战士
蓝腮战士
鱼人领军
鱼人领军
寒光智者
寒光智者
跟你说个笑话,圣骑士的斩杀
呜啦啦啦啦呱啦哈哈!
跟你说个笑话,圣骑士的斩杀
Program ended with exit code: 0