题解 | #Pokemon#
Pokemon
http://www.nowcoder.com/practice/a4cc4ef629f146f68c5d02e06dfd6b99
思路:
题目的主要信息:
- 皮卡丘的生命值是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; } };
复杂度分析:
- 时间复杂度: ,没有循环
- 空间复杂度: ,只使用了常数空间