动态规划-打气球的最大分数(python实现)

算法题:打气球的最大分数

最近在看左程云的《程序员代码面试指南》,感觉不错,题都分了类,很方便有目的的刷题,书里的代码都是java实现的,刚好最近在学习python,就用python去练习一下。

1. 问题描述

给定一个数组arr,代表一排有分数的气球。 每打爆一个气球都能获得分数,假设打爆气球的分数为X,获得分数的规则如下:

1)如果被打爆气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为L:如果被打爆气球的右边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为R.获得分数为LXR
2)如果被打爆的气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为L:如果被打爆气球的右边所有气球都已经被打爆,获得分数为LX。
3)如果被打爆气球的左边所有的气球都已经被打爆:如果被打爆气球的右边有没被打爆的气球,找到离被打爆气球最近的气球。获得分数为XR.
4)如果被打爆气球的左边和右边所有的气球都已经被打爆。获得分数为X。

目标是打爆所有气球,获得每次打爆的分数。通过选择打爆气球的顺序,可以得到不同的总分,请返回能获得的最大分数

2.解决方法

1)暴力递归:假设arr[L-1]和arr[R+1]都没爆,要打爆arr[L]到arr[R]的气球,假设arr为[L~R],可以设置一个help数组,添加arr[L-1]和arr[R+1]并将值值设为1。如此便对于相乘便无影响。对于L和R位置,对于普通位置i分别递归地求解。
2)动态规划:以L和R为可变参数作m表,将表画出可以发现,m[i][j]代表i~j上打爆所有气球的最大分数,对于每个位置,其值只依赖于其左侧和正下方的值。则从下往上的完成m表,可以得到结果。

3.代码实现

暴力递归
# 暴力递归
def process(arr, L, R):
    if L == R:
        return arr[L-1] * arr[L] * arr[R+1]
    
    max_score = max(arr[L-1] * arr[L] * arr[R+1] + process(arr, L+1, R), arr[L-1] * arr[R] * arr[R+1] + process(arr, L, R-1))

    for i in range(L+1, R):
        max_score = max(max_score, arr[L-1] * arr[i] * arr[R+1] + process(arr, L, i-1) + process(arr, i+1, R))
    
    return max_score

动态规划

# 动态规划
def score(arr):
    m = [[0 for i in range(len(arr))] for j in range(len(arr))]

    for i in range(1, len(arr)-1):
        m[i][i] = arr[i-1] * arr[i] * arr[i+1]
    
    # 求解m[i][j],m[i][j]代表i~j上打爆所有气球的最大分数
    L = len(arr) - 2
    while L >= 1:
        R = L + 1
        while R <= len(arr) - 2:
            # 最后打爆arr[L]的情况
            finalL = arr[L-1] * arr[L] * arr[R+1] + m[L+1][R]
            # 最后打爆arr[R]的情况
            finalR = arr[R+1] * arr[R] * arr[L-1] + m[L][R-1]
            # 先比较一下arr[L]和arr[R]的情况
            m[L][R] = max(finalL, finalR)
            # 对一般情况进行分析
            for i in range(L+1, R):
                m[L][R] = max(m[L][R], arr[L-1] * arr[i] * arr[R+1] + m[L][i-1] + m[i+1][R])
            R += 1
        L -= 1
	
	print("m表:")
    for item in m:
        for i in item:
            print(i, end = '\t')
        print()
    return m[1][len(arr)-2]


if __name__ == "__main__":
    help_arr = [1, 4, 2, 3, 5, 1, 6, 1]
    print("(递归)最大分数为:{0}".format(process(help_arr, 1, 6)))
    print("(动态规划)最大分数为:{0}".format(score(help_arr)))

结果:

(递归)最大分数为:264
m表:
0       0       0       0       0       0       0       0
0       8       36      104     109     258     264     0
0       0       24      84      104     234     258     0
0       0       0       30      40      156     168     0
0       0       0       0       15      120     138     0
0       0       0       0       0       30      60      0
0       0       0       0       0       0       6       0
0       0       0       0       0       0       0       0
(动态规划)最大分数为:264
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值