中等算法刷题-小E的怪物挑战| 豆包MarsCode AI刷题

130 阅读2分钟

在刷题的过程中,遇到了这样一道题目:

小E在一个游戏中遇到了nn个怪物。每个怪物都有其特定的血量hihi​和攻击力aiai​。小E的初始血量为HH,攻击力为AA。她可以击败那些血量和攻击力都小于她自身的怪物。每击败一个怪物后,小E的血量和攻击力会变为该怪物的血量和攻击力。小E想知道,她最多能击败多少怪物。

一开始啊我是想这道题可以先排序然后再进行遍历,如果自身血量大于怪物的话,那么直接将怪物血量赋给自身血量再接着进行遍历即可,我也是这样写的代码,但是写出来报错了,是第二个测试用例报的错,

输入:`n = 5, H = 10, A = 10, h = [6, 9, 12, 4, 7], a = [8, 9, 10, 2, 5]`  
输出:`2`

我就在想会不会是题目给测试用例给错了,但是后来想应该不会,应该是我理解题目理解错了,我就去社区里找了找有没有大佬写出这道题分享出来的,就找到了这位大佬的文章:juejin.cn/post/743842… 看了一下这位大佬的文章,我才知道,原来这道题目的顺序应该是从右往左的,从测试用例推断出来的,从右往左遍历,求最大的能击败怪物的数目,其实就相当于从右往左依次从大到小,那正过来就是从左往右,依次从小到大,求最大长度的子序列,那这么一想,其实就可以用动态规划来解决这道题目,这个也是看的这位大佬的思路,那我也就直接留一下代码,这位大佬的文章里还有类似的题目以及其他算法的解法,可以去看一看。

这里解释一下下面的代码,先创建一个数组用来存储第i个元素之前的最长的递增的子序列的长度,然后初始化为1,(自身长度为1),如果说碰到的怪物的一项属性比自身大,就直接跳过,如果比自身小,那么进入第二个循环,看从0到i的序列中,最长的递增子序列的长度是多少,然后与max比较,max记录最大值。

public static int solution(int n, int H, int A, int[] h, int[] a) {
        // write code here
                int[] dp = new int[n];
                int max = 0;
                for (int i = 0; i < n; i++) {
                    if (h[i] >= H || a[i] >= A) {
                        continue;
                    }
                    dp[i] = 1;
                    for (int j = 0; j < i; j++) {
                        if (h[i] > h[j] && a[i] > a[j]) {
                            dp[i] = Math.max(dp[i], dp[j] + 1);
                        }
                    }
                    max = Math.max(max, dp[i]);
                }
                return max;
    }