再学动态规划之 完全背包

版权声明:本文为博主原创文章,转载请标明出处~ https://blog.csdn.net/Love_wanling/article/details/83096790

LeetCode: https://leetcode.com/problems/coin-change/description/
在这里插入图片描述

暴力搜索

考虑当前index 拿1张,2张,…时候,从index+1开始的最小张数。相加即可:

import sys
class Solution(object):

    def get_small_number(self, coins, index, amount):
        if amount == 0:
            return 0
        if amount < 0:
            return -1
        if index == len(coins)-1:
            if amount%coins[index] != 0:
                return -1
            else:
                return amount/coins[index]
        min_res = sys.maxint
        for i in range(amount/coins[index] + 1):
            back_amount = self.get_small_number(coins, index+1, amount-i*coins[index])
            this_amount = back_amount + i
            if back_amount == -1:
                this_amount = sys.maxint
            min_res = min(min_res, this_amount)
        return min_res

    def coinChange(self, coins, amount):
        """
        :type coins: List[int]
        :type amount: int
        :rtype: int
        """
        return -1 if self.get_small_number(coins, 0, amount) == sys.maxint else self.get_small_number(coins, 0, amount)

记忆化搜索

当前的问题就是,每次都没有把结果记录下来,导致重复计算。故 超时
比如[1 ,2, 5] 目标是 11 的时候。1拿2张,2拿0张 和 1拿0张,2拿1张;应该是一种情况。

import sys
res = dict()
class Solution(object):

    def get_small_number(self, coins, index, amount):
        if amount == 0:
            return 0
        if amount < 0:
            return -1
        if index == len(coins)-1:
            if amount%coins[index] != 0:
                return -1
            else:
                return amount/coins[index]
        if str(index)+'_'+str(amount) in res:
            return res[str(index)+'_'+str(amount)]
        min_res = sys.maxint
        for i in range(amount/coins[index] + 1):
            back_amount = self.get_small_number(coins, index+1, amount-i*coins[index])
            this_amount = back_amount + i
            if back_amount == -1:
                this_amount = sys.maxint
            min_res = min(min_res, this_amount)
        res[str(index)+'_'+str(amount)] = min_res
        return min_res


    def coinChange(self, coins, amount):
        """
        :type coins: List[int]
        :type amount: int
        :rtype: int
        """
        res.clear()
        return -1 if self.get_small_number(coins, 0, amount) == sys.maxint else self.get_small_number(coins, 0, amount)

这次记忆化搜索都超时了诶。。。

动态规划

状态转移方程式:
dp[i][j]=mint[0,1+j/coins]{t+dp[i1][jcoins[i]t]}dp[i][j]=min_{t\in[0,1+j/coins]}\{t+dp[i-1][j-coins[i]*t]\}

import sys
class Solution(object):
    def coinChange(self, coins, amount):
        """
        :type coins: List[int]
        :type amount: int
        :rtype: int
        """
        arr = [[sys.maxint for _ in range(amount+1)] for _ in range(len(coins)+1)]
        for ix in range(len(coins)+1):
            arr[ix][0] = 0
        for i in range(1, len(coins)+1):
            for j in range(1, amount+1):
                res_min = arr[i-1][j]
                for t in range(1, j/coins[i-1]+1):
                    res_min = min(res_min, t+arr[i-1][j-coins[i-1]*t])
                arr[i][j] = res_min


        return -1 if arr[-1][-1] == sys.maxint else arr[-1][-1]

依然超时呢。还有什么优化空间吗?
我把递推公式展开来写,你就会发现所谓的优化空间了;
dp[i][j]=min{dp[i1][j],1+dp[i1][jx],2+dp[i1][j2x]+...}dp[i][j] = min\{dp[i-1][j],1+dp[i-1][j-x],2+dp[i-1][j-2x]+...\}
dp[i][jx]=min{dp[i1][jx],1+dp[i1][j2x],2+dp[i1][j3x]+...}dp[i][j-x] =min\{dp[i-1][j-x],1+dp[i-1][j-2x],2+dp[i-1][j-3x]+...\}
所以:
dp[i][j]=min{dp[i1][j],1+dp[i][jx]}dp[i][j] = min\{dp[i-1][j],1+dp[i][j-x]\}

import sys
class Solution(object):
    def coinChange(self, coins, amount):
        """
        :type coins: List[int]
        :type amount: int
        :rtype: int
        """
        arr = [[sys.maxint for _ in range(amount+1)] for _ in range(len(coins)+1)]
        for ix in range(len(coins)+1):
            arr[ix][0] = 0
        # arr[:][0] = 1
        for i in range(1, len(coins)+1):
            for j in range(1, amount+1):
                res_min = arr[i-1][j]
                if j - coins[i-1] >= 0:
                    res_min = min(res_min, 1+arr[i][j-coins[i-1]])
                arr[i][j] = res_min
        return -1 if arr[-1][-1] == sys.maxint else arr[-1][-1]
展开阅读全文

没有更多推荐了,返回首页