【动态规划】找零钱问题解析(含c++和python代码)

一个具体的找零钱问题:

参考:程序员面试再也不怕动态规划了,看动画,学DP,找零钱 (LeetCode 322)

【动态规划】找零钱问题解析(含c++和python代码)_第1张图片

硬币面值:1,2,5,7,10
找零金额:14

  • step1:定义长度为15的dp数组
    所有元素初始化为-1, d p [ 0 ] = 0 dp[0] = 0 dp[0]=0
    【动态规划】找零钱问题解析(含c++和python代码)_第2张图片
  • step2:遍历coins列表找出小于金额的硬币面值 j j j,接着再使用 d p [ i − c o i n s [ j ] ] dp[i-coins[j]] dp[icoins[j]]来找出 i − c o i n s [ j ] i-coins[j] icoins[j]的最优解;最终金额 i i i的最优解为 1 + d p [ i − c o i n s [ j ] ] 1+dp[i-coins[j]] 1+dp[icoins[j]]
    d p [ 1 ] = d p [ 0 ] + 1 = 1 dp[1]=dp[0]+1=1 dp[1]=dp[0]+1=1
    d p [ 2 ] = d p [ 0 ] + 2 dp[2]=dp[0]+2 dp[2]=dp[0]+2 d p [ 2 ] = d p [ 1 ] + 1 dp[2]=dp[1]+1 dp[2]=dp[1]+1,而 d p [ 0 ] < d p [ 1 ] dp[0]dp[0]<dp[1],故 d p [ 2 ] = d p [ 0 ] + 2 = 1 dp[2]=dp[0]+2=1 dp[2]=dp[0]+2=1
    d p [ 3 ] = 1 + d p [ 2 ] dp[3]=1+dp[2] dp[3]=1+dp[2] d p [ 3 ] = 2 + d p [ 1 ] dp[3]=2+dp[1] dp[3]=2+dp[1],而 d p [ 1 ] = d p [ 2 ] = 1 dp[1]=dp[2]=1 dp[1]=dp[2]=1,故 d p [ 3 ] = 1 + 1 = 2 dp[3]=1+1=2 dp[3]=1+1=2
    d p [ 4 ] = 1 + d p [ 3 ] dp[4]=1+dp[3] dp[4]=1+dp[3] d p [ 4 ] = 2 + d p [ 2 ] dp[4]=2+dp[2] dp[4]=2+dp[2],而 d p [ 2 ] < d p [ 3 ] dp[2]dp[2]<dp[3],故 d p [ 4 ] = 2 dp[4]=2 dp[4]=2
    d p [ 5 ] = d p [ 0 ] + 1 = 1 dp[5]=dp[0]+1=1 dp[5]=dp[0]+1=1
    d p [ 6 ] = 1 + d p [ 5 ] dp[6]=1+dp[5] dp[6]=1+dp[5] d p [ 6 ] = 2 + d p [ 4 ] dp[6]=2+dp[4] dp[6]=2+dp[4] d p [ 6 ] = 5 + d p [ 1 ] dp[6]=5+dp[1] dp[6]=5+dp[1]
    同理,计算出剩下所有金额的最优解:

【动态规划】找零钱问题解析(含c++和python代码)_第3张图片

【动态规划】找零钱问题解析(含c++和python代码)_第4张图片

C++版

using namespace std;
class Solution{
public:
	int coinChange(vector<int>&coins,int amount){
		vector<int>dp(amount+1,-1);
		dp[0]=0;
		for(int i=1;i<=amount;i++){
			for(int j=0;j<coins.size();j++){
				if(coins[j]<=i&&dp[i-coins[j]!=-1){
				//如果当前金额还未计算或者dp[i]比正在计算的解大,则更新最优解dp[i]
					if(dp[i]==-1||dp[i]>dp[i-coins[j]]+1)
						dp[i]=dp[i-coins[j]]+1;
				}
			}
		}
		return dp[amount]	//返回金额amount的最优解
	}	
}

python版

采用动态规划编写一个找零钱函数dpMakeChange,接收硬币面值列表coinValueList和找零金额change两个参数,返回change对应的最少硬币数的找零详情字典(包含所用的每种硬币面值和个数)。

def dpMakeChange(coinValueList, change):
    minCoins = [0] * (change + 1)#初始化minCoins列表为0
    coinsUsed = {}#保存的是找零钱change最后一枚找的币值
    for cents in range(change + 1):
        coinCount = cents#初始化硬币数量为金额cents
        newCoin = 1
        #遍历硬币列表coinValueList,遍历小于金额cents的硬币面值
        for j in [c for c in coinValueList if c <= cents]:
        	#如果当前正在求的最优解小于当前金额的coinCount,则更新coinCount值
            if minCoins[cents - j] + 1 < coinCount:
                coinCount = minCoins[cents - j] + 1
                newCoin = j
        minCoins[cents] = coinCount#把最优的coinCount值放入minCoins表中
        coinsUsed[cents] = newCoin
    changeDetails = {}#保存找零金额change对应最少硬币数的找零详情字典
    while change > 0:
        thisCoin = coinsUsed[change]
        if thisCoin in changeDetails:
            changeDetails[thisCoin] += 1
        else:
            changeDetails[thisCoin] = 1
        change -= thisCoin
    return changeDetails

你可能感兴趣的:(动态规划,c++,算法,python)