Hearthstone Battlegrounds

题意(简洁写,牛客机翻太不友好,可能描述不太准确):生物A有4种类别:
1.剧毒+圣盾+召唤(机翻脱锤emm)
2.剧毒+圣盾
3.剧毒+召唤
4.剧毒

剧毒效果:无盾情况下即死,有盾情况下破盾,作为防守方剧毒可以即死进攻方,进攻方可以即死防守方,双方都有剧毒效果时双方同归于尽
圣盾效果:抵挡一次任意伤害
召唤效果:死后召唤生物B,B的属性:一攻一血,(A因为都有剧毒视作攻击力无穷大,血量无穷大,只有即死可以杀死)

规则:每个回合只能有一个生物行动,当一方场上还有A或B,另一方场上无A和B,则获胜。现在给出甲乙两方上述4种A的数量,问甲方有没有希望获胜。

题目问的是有没有希望获胜,所以我们找获胜概率最大的方式进行判定结果:甲方始终做最优选择,而乙方傻夫夫的始终做最差选择。所以我们需要找到怎样的行动是最优的,什么行动是最差的。

B一血一攻的属性显然难堪大用,只能作为牺牲品去破盾,如果破盾有剩余则留下来,如果最后A双方都没了,甲要获胜则甲的B的数量大于乙的B的数量,所以有机会的话要干掉乙的B,当然,只要对方还有1只A,那么甲方输。而B的最差用法就是最后给A送人头,先打光所有的A,如果双方都没A在和甲方的B打。
我们发现因为A都具有剧毒效果,所以乙方攻击甲方和甲方攻击乙方效果相同,所以我们视为始终都是甲方攻击,一开始双方都没有B,所以甲方应该尽快用召唤去和对方的无盾A换血,然后用召唤的B去破盾,如果甲方没有了召唤,那么两方只能一换一了,如果甲方还有召唤,但乙方只剩下有盾A,先用召唤和对面换血必然是不亏的,所以我们此时继续用召唤去和对面换血,遵循上述规则,直到一方/双方场上没有A。

补题参考题解

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<map>

typedef long long ll;

using namespace std;
char str[20010];
long long sum;

const int N = 1e5 + 10;

int a, b, c, d, e, f, g, h, s1 = 0, s2 = 0;

bool solve() {//进行操作,直到一方场上无A
	if (s1 && e) { s1--; e--; g++; return true; }//尝试破盾
	if (s1 && f) { s1--; f--; h++; return true; }
	if (c && g) { s1++; c--; g--; s2++;  return true; }//召唤和对方无盾同归于尽
	if (c && h) { s1++; c--; h--; return true; }
	if (a && g) { a--; c++; g--; s2++; return true; }
	if (a && h) { a--; c++; h--; return true; }
	if (c && e) { s1++; c--; e--; g++; return true; }//对方剩下的都是带盾的,只能和对方带盾的开始换
	if (c && f) { s1++; c--; f--; h++; return true; }
	if (a && e) { a--; c++; e--; g++; return true; }
	if (a && f) { a--; c++; f--; h++; return true; }
	if (b && e) { d++; b--; e--; g++; return true; }//无法召唤B了,随便攻击
	if (b && f) { b--; d++; f--; h++; return true; }
	if (b && g) { b--; d++; g--; s2++; return true; }
	if (b && h) { b--; d++; h--; return true; }
	if (d && e) { d--; e--; g++; return true; }
	if (d && f) { d--; f--; h++; return true; }
	if (d && g) { d--; g--; s2++; return true; }
	if (d && h) { d--; h--; return true; }
	return false;
}

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		s1 = s2 = 0;
		scanf("%d %d %d %d", &a, &b, &c, &d);
		scanf("%d %d %d %d", &e, &f, &g, &h);
		while (solve()) {
			if (a || b || c || d) s2 = 0;//当甲方还有A时干掉乙方的B,为两方只剩B时取得优势
		}
		if (a + b + c + d > 0) {
			printf("Yes\n");
		}
		else if (e + f + g + h > 0) {
			printf("No\n");
		}
		else {
			if (s1 > s2) printf("Yes\n");
			else printf("No\n");
		}
	}
}

我中途想了这样一个方法:按可承受攻击次数作为血条,则无圣盾的具有1点血,有圣盾的具有两点血,然后对甲方的召唤A进行讨论,即它可以减少乙方的血量,最后比较剩余血量多少,然后WA了,但竟然过了82%的数据,然后就一直钻,后来想了想原因应该是无法将A召唤出的B对乙方的伤害即时体现(也许可行,但可惜蒟蒻不会)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值