思路:
题目的主要信息:
- 皮卡丘的生命值是HP,攻击力是ACK;杰尼龟的生命值是HP2,攻击力是ACK2。
- 杰尼龟在每回合开始前可以吃药满血复活,但吃药后不得在本回合发动攻击。
- 皮卡丘比杰尼龟先发动攻击。若能成功击败皮卡丘则返回最少回合数,否则返回-1。
方法一:暴力
首先解决一些特殊情况:
a.HP2<ACK,杰尼龟第一局就被皮卡丘打倒,返回-1;
b.HP<=ACK2,杰尼龟第一局就把皮卡丘打倒,返回1;
其他情况以模拟战斗过程进行分析,若第round局结束后杰尼龟当前的血量低于ACK,表示杰尼龟必须吃药恢复血量,同时本局不能进攻,仍受到皮卡丘的攻击;若杰尼龟当前的血量高于ACK,则这一局可以发起进攻;
模拟对战如下图所示:
c.HP2-ACK<ACK,杰尼龟第一局不会被打倒,但一直处于复活的死循环中,返回-1;
具体做法:
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param HP long长整型 HP
* @param ACK long长整型 ACK
* @param HP2 long长整型 HP2
* @param ACK2 long长整型 ACK2
* @return long长整型
*/
long long Pokemonfight(long long HP, long long ACK, long long HP2, long long ACK2) {
// write code here
if(ACK>=HP2||((HP2-ACK)<=ACK&&HP>ACK2))//杰尼龟第一回合就被打死或者处于***复活的死循环
{
return -1;
}
if(HP<=ACK2)//第一局杰尼龟打败了皮卡丘
{
return 1;
}
int round=0;
int pikapika=HP2;//pikapika代表杰尼龟当前的剩余血量
while(HP>0)//皮卡丘还没被打败时,继续战斗
{
if(pikapika>ACK)//杰尼龟目前剩余血量还能扛住皮卡丘再一轮进攻时
{
pikapika-=ACK;//皮卡丘进攻
HP-=ACK2;//杰尼龟进攻
}else{//杰尼龟扛不住进攻了,***
pikapika=HP2-ACK;//杰尼龟恢复血量至HP2,皮卡丘发动进攻
}
round++;
}
return round;
}
};复杂度分析:
- 时间复杂度:
,最差情况为皮卡丘的血量HP。
- 空间复杂度:
,只用了常数空间。
方法二:数学方法
首先计算如果纯攻击的话,需要多少回合能打败皮卡丘,对HP%ACK2 进行判断,如果HP%ACK2为0,则刚好HP/ACK2回合可以打败皮卡丘;若HP%ACK2不为0,则需要多一回合。
然后计算杰尼龟在多少个回合后需要吃药。对HP2%ACK进行判断,若HP2%ACK为0,则表示HP2/ACK回合后,杰尼龟就死亡了,因此必须在HP2/ACK-1回合时就吃药;若HP2%ACK不为0,表示HP2/ACK后杰尼龟还有剩余血量,可以在HP2/ACK回合后再吃药;
最后计算杰尼龟在和皮卡丘战斗的过程中需要吃几次药。
由于第round回合就把皮卡丘打败了了,杰尼龟不用吃药,所以只要考虑前round-1次的吃药次数。
由于皮卡丘是先手,所以不能等到杰尼龟drug_round后再吃药,所以杰尼龟必须在drug_round-1回合后就吃药。因此(round-1)/(drug_round-1)表示杰尼龟吃药的回合数。对(round-1)%(drug_round-1)进行判断,若为0,我们剔除最后一次回血的情况;若不为0,则返回(round-1)/(drug_round-1)。
具体做法:
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param HP long长整型 HP
* @param ACK long长整型 ACK
* @param HP2 long长整型 HP2
* @param ACK2 long长整型 ACK2
* @return long长整型
*/
long long Pokemonfight(long long HP, long long ACK, long long HP2, long long ACK2) {
if(ACK >= HP2 || (ACK2 < HP && ACK*2 >= HP2))
{
return -1;
}
// 皮卡丘第一局就被打死
if(HP <= ACK2)
{
return 1;
}
// round为打败皮卡丘需要的回合数
long long round;
if(HP%ACK2 == 0)
{
round=HP/ACK2;
}else{
round=(HP/ACK2)+1;
}
// drug_round为每次满血复活后可以撑多少回合不吃药
long long drug_round;
if(HP2%ACK == 0)
{
drug_round=(HP2/ACK)-1;
}else{
drug_round=(HP2/ACK);
}
//count为需要吃药的回合数
long long count=0;
if(round < drug_round)//不需要吃药
{
return round;
}else {//计算吃药次数
if((round-1)%(drug_round-1)==0)
{
count=(round-1)/(drug_round-1)-1;
}else{
count=(round-1)/(drug_round-1);
}
}
//最后返回吃药回合数+攻击回合数
return count+round;
}
};复杂度分析:
- 时间复杂度:
,没有循环
- 空间复杂度:
,只使用了常数空间

京公网安备 11010502036488号