[编程题]牛妹打怪兽(牛客网编程题)的动态规划AC解

链接:https://www.nowcoder.com/questionTerminal/5c5fa5bf2a9942fcb1a3844d715087b9
来源:牛客网

众所周知,牛妹非常喜欢打游戏,在阳光明媚的一天,她在玩一个叫做打怪兽的游戏。
也许您已经知道游戏“打怪物”。如果您不知道,没关系,让我现在告诉您,森林里有那么多怪物,您就是攻击怪物并保护村庄的英雄。
为了简化问题,我们把怪物排成一行,怪物身上有很多攻击点,你有一把剑,只能切掉攻击点,当切掉一个攻击点时,怪物会分裂成两个在段中,您必须消耗与怪物一样多的能量。您的任务是将怪物切割成不包含任何攻击点。例如,您面对一个怪物,该怪物的长度为20,并且有四个攻击点在其主体上:2 5 10 18.您可以这样切割:
1.切开第一点,您使用的能量为2 + 18 = 20;
2.切第二点,您使用的能量为3 + 15 = 18;
3.切第三点,您使用的能量为5 + 10 = 15;
4.切第四点,您使用的能量是8 + 2 = 10;
您使用的总能量为:20 + 18 + 15 + 10 = 63;
但您可以采用另一种策略:
1.切第二点,您使用的能量是5 + 15 = 20;
2.切开第一点,您使用的能量为2 + 3 = 5;
3.切第三点,您使用的能量是5 + 10 = 15;
4.切第四个点,您使用的能量为8 + 2 = 10;
您使用的能量为:20 + 5 + 15 + 10 = 50;
因此您有最佳的策略来最小化需要消耗的能量。
那么问题来了,牛妹面对给定攻击点和长度的怪兽,到底最后可以用最少多少的能量打倒怪兽呢?

假设原来的弱点数组为l
对l排序后
将0后末尾也加入进去
即l = [0] + l + [length]
根据题目的意思,我们只能选弱点来切
则可以切的地方只有弱点
定义DP[x][y]为从第x个弱点(按从第0个到倒数第二个算)切到第j个(从第2个到最后一个算)所需能量
显然 DP[i][i] = 0(注意 两个i的起始坐标不一样 因此虽然是DP[i][i] 但是是从第i个切到第i-1个)
也就是说 从第i个 到第i-1个这种 中间不含其它弱点的段 不用切 能耗=0
而DP[i][i+1] = l[i+1 + 1] - l[i]
此后 dp[i][j] = l[i+1 + 1] - l[i] + min(dp[i][i+t],dp[i+t+1][j])其中t >0 且 i+t+1 <= j



#
# 
# @param monsterLength int整型 怪兽长度
# @param monsterPoint int整型一维数组 怪兽攻击点位置
# @return int整型
#
class Solution:
    def attackMonster(self , monsterLength , monsterPoint ):
        # write code here
        monsterPoint = sorted(monsterPoint)
        m = len(monsterPoint) + 1
        dp = []
        for i in range(m):
            dp.append([0 for _ in range(m)])
        monsterPoint = [0] + monsterPoint + [monsterLength]
        for i in range(1,m):
            for j in range(m-i):
                base = monsterPoint[j+i+1]-monsterPoint[j]
                minres = None
                for k in range(j,j+i):
                    if minres == None:
                        minres = base + dp[j][k] + dp[k+1][j+i]
                    else:
                        minres = min(minres,base + dp[j][k] + dp[k+1][j+i])
                dp[j][j+i] = minres
        return dp[0][-1]

猜你喜欢

转载自blog.csdn.net/weixin_41545780/article/details/107725767