雷火盘古笔试题《打怪兽》到底该怎么打才比较快?

打怪兽
想来也被这道题困扰了十多天了。:<
这是我当时的代码,用了BFS的思路(贼傻瓜),只通过了20%的测试用例,时间复杂度太高了。现在也没想出比较好的方法,求一个茅塞顿开啊!

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
#include <queue>

using namespace std;

/*
Approach:
BFS
*/

struct Node {
    int HP;
    int AP;
    int HM;
    int AM;
};

int main()
{
    int HP = 0, AP = 0, HM = 0, AM = 0, B = 0, D = 0;
    cin >> HP >> AP >> HM >> AM >> B >> D;

    Node curr { HP, AP, HM, AM };
    queue<Node> Q;
    int step = 0;
    Q.push(curr);

    while (!Q.empty())
    {
        int size = Q.size();
        // 出队队列当前所有元素
        for (int i = 0; i < size; ++i)
        {
            Node curr = Q.front();
            Q.pop();

            // 若怪兽血量降为0,则获胜,(因为人先攻击,即使这个时候人的血量也降为0,依然是人胜利)
            if (curr.HM <= 0)
            {
                cout << step << endl;
                return 0;
            }
            // 若当前节点HP已经降为0,则此状态失败,到下一个节点
            if(curr.HP <= 0)
                continue;

            // attack 分支
            Node attack { curr.HP - curr.AM, curr.AP, curr.HM - curr.AP, curr.AM };
            // recover 分支
            Node recover { HP - curr.AM, curr.AP, curr.HM, curr.AM };
            // enhance 分支
            Node enhance { curr.HP - curr.AM, curr.AP + B, curr.HM, curr.AM };
            // weaken 分支
            curr.AM = max(0, curr.AM - D);
            Node weaken { curr.HP - curr.AM, curr.AP, curr.HM, curr.AM };
            Q.push(attack);
            Q.push(recover);
            Q.push(enhance);
            Q.push(weaken);
        }
        ++step;
    }

    cout << "IMPOSSIBLE" << endl;

    return 0;
}
#笔试题目##实习#
全部评论
充钱
点赞 回复 分享
发布于 2018-04-11 18:13
作者:Leoric 链接:https://www.nowcoder.com/discuss/73357 来源:牛客网       首先计算出假设你是无敌状态(不会死亡)至少需要多少步打死怪兽,先进行a次加攻击操作,再进行b次攻击操作,且a+b最小。这个结果可遍历得到(可能列式直接计算也行)。这样,就把加攻击和攻击两种操作合并了,称为杀怪操作,并设这个操作最小次数为c。复杂度O(100*100)。       接着考虑生存方面,同样,把回血和减攻合并为防御操作。显然,我们需要先进行防御操作,使怪兽的攻击和自身的生命值足以让我们进行c次攻击操作。在防御操作中,我们应该尽可能地把减攻操作给安排在前面,即如果整个战略中还需要进行减攻操作且自身当前的生命值大于怪兽攻击力,则必然进行减攻操作。另外,假设我们完成了减攻操作,则进行d次回复,使得能够进行c次攻击且自身不会死亡。因此,可以从初始状态出发,令step=0。然后循环使step++,并且如果怪兽攻击力大于生命值,则回复生命值,否则减少怪兽攻击力,对于每个step,可以用O(1)的复杂度直接计算出回复次数d,则总步数为step+d+c。这样计算得到多个总步数,取最小值就得到最终结果。复杂度O(100)。         
点赞 回复 分享
发布于 2018-04-12 04:27
我在等题目会不会放出来,网易互联网第二天就有了。
点赞 回复 分享
发布于 2018-04-11 15:38
我也是BFS20,可能要用DP吧,但是不知道怎么推
点赞 回复 分享
发布于 2018-04-11 18:16
并不是每次搜索到的状态都加入队列里面,如果当前搜索到的状态在之前已经加入过队列一次,这个状态就不需要再加入队列了,因为之前已经出现过回合数少的这个状态了
点赞 回复 分享
发布于 2018-04-11 18:23

相关推荐

过往烟沉:我说什么来着,java就业面就是广!
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务