消灭最终BOSS

这是一篇关于解决华为机试中的一款回合制游戏问题的博客。玩家需击败拥有特定攻击模式的BOSS,通过分析不同魔法值下的策略,博主提出了在魔法量充足时优先使用魔法攻击,不足时根据BOSS血量和魔法恢复情况选择最佳行动方案。文章最初采用贪心算法,后来转向动态规划来优化解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

消灭最终BOSS

题目来源:华为机试题

某游戏中,玩家的任务是杀死终极BOSS。BOSS和玩家战斗方式为回合制,玩家先发动进攻。BOSS的攻击方式为:普通攻击和暴击,每4回合普通攻击的下一回合攻击为暴击。BOSS的普通攻击力为10点HP,暴击时的攻击力为普通攻击的3倍。玩家的攻击方式为:普通攻击和魔法攻击。玩家的普通攻击为17点HP,魔法攻击为60点HP。使用魔法攻击时需要消耗10点魔法值,魔法值来源有两种:初始魔法量和回合内选择魔法恢复,魔法恢复速度为4点/回合,魔法恢复回合内无法发动攻击。每轮回合开始时,玩家可以选择:普通攻击、魔法攻击或恢复魔法三种行动方式之一。现已知玩家的HP和初始魔法量,BOSS的HP,编写程序,求玩家战胜BOSS的最小回合数。

1 Sec

100 MByte

输入三个整数HP(0<HP1<=10000),MP(0<MP<=1000),HP2(0<HP2<=10000),分别为玩家的HP、玩家的初始魔法量和BOSS的HP。

若玩家可以战胜BOSS输出战胜BOSS的最小回合数,否则输出-1.

100 20 100

2


思路:由于本人是刚接触编程不久的菜鸟,目前还不会使用动态规划和贪心算法,所以用现有的水平分析一下这道题。

1. 如果MP(魔法量)>=10,我们总是可以选择魔攻造成60点伤害;

2. 如果6<=MP<10,BOSS血量高于34,选择魔回+魔攻造成60点伤害;

3. 如果2<=MP<6,BOSS血量高于51,选择魔回*2+魔攻造成60点伤害;

4. 如果MP<2,此时需要综合考虑,回魔*5+魔攻*2可造成120点伤害,同样回合数普攻*7可造成119点伤害,所以,如果BOSS血量不高于119,只进行普攻就可以得到最优方案,如果BOSS血量高于119,选择回魔*5+魔攻*2可以造成更多伤害。

因此,我的代码如下:

#include <stdio.h>

int main()
{
	int playerhp, playermp, bosshp;

	while(scanf("%d%d%d", &playerhp, &playermp, &bosshp) != EOF) {
		int countbossdeath = 0, countplayerdeath = 0;
		while(bosshp > 0) {
			if(playermp >= 10) {
				bosshp -= 60;
				playermp -= 10;
				countbossdeath++;
			} else if(playermp >= 6 && playermp < 10) {
				if(bosshp <= 34) {
					countbossdeath += (bosshp + 16) / 17;
					bosshp -= 34;
				} else {
					bosshp -= 60;
					playermp -= 6;
					countbossdeath += 2;
				}				
			} else if(playermp >= 2 && playermp < 6) {
				if(bosshp <= 51) {
					countbossdeath += (bosshp + 16) / 17;
					bosshp -= 51;
				} else {
					bosshp -= 60;
					playermp -= 2;
					countbossdeath += 3;
				}				
			} else {
				if(bosshp <= 119) {
					countbossdeath += (bosshp + 16) / 17;
					bosshp -= 119;
				} else {
					bosshp -= 120;
					countbossdeath += 7;
				}
			}
		}
		while(playerhp > 0) {
			if(countplayerdeath != 4)
				playerhp -= 10;
			else
				playerhp -= 30;
			countplayerdeath++;
		}
		if(countplayerdeath >= countbossdeath)
			printf("%d\n", countbossdeath);
		else
			printf("-1\n");
	}
	return 0;
}

经过大神指导,才明白以上代码属于贪心算法,现在使用动态规划解决问题,代码如下:

#include <stdio.h>

int bossattack(int hp)
{
	int ret, rem;

	ret = hp / 70 * 5;			// BOSS每5回合造成70点伤害
	rem = (hp % 70 + 9) / 10;
	if(rem > 4)
		ret += 5;
	else
		ret += rem;
	return ret;
}

int record[1001][10001];

int playerattack(int mp, int hp)
{
	int r1, r2;
	if(hp <= 0)
		return 0;
	if(record[mp][hp] != -1)
		return record[mp][hp];
	if(mp >= 10)
		return record[mp][hp] = 1 + playerattack(mp-10, hp-60);
	else {
		r1 = 1 + playerattack(mp+4, hp);
		r2 = 1 + playerattack(mp, hp-17);
		return record[mp][hp] = (r1 < r2 ? r1 : r2);
	}
}

int main()
{
	int playerhp, playermp, bosshp;

	while(scanf("%d%d%d", &playerhp, &playermp, &bosshp) != EOF) {
		int i, j, bossdead, playerdead;
		for(i = 0; i < 1001; i++)
			for(j = 0; j < 10001; j++)
				record[i][j] = -1;
		playerdead = bossattack(playerhp);
		bossdead = playerattack(playermp, bosshp);
		if(playerdead < bossdead)
			printf("-1\n");
		else
			printf("%d\n", bossdead);
	}
	return 0;
}



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值