首页 > 技术文章 > 动态规划-换钱最少货币数

BetterThanEver_Victor 2017-09-21 18:42 原文

#encoding:utf-8
_author_ = "Wang Wenchao"
#换钱最少的货币数
#给定数组arr,arr中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个正数aim代表要找的钱数,求组成aim的最少货币数
''' arr=[5,2,3],aim=20
    4张5元可以组成20元,所以返回4
    arr=[5,2,3],aim=0
    返回0
    arr=[3,5],aim=2
    返回-1
'''
#解法:arr长度为N,生成行数为N的,列数为aim+1的二维数组dp# ,dp[i][j]表示使用arr[0...i]的时候组成aim需要最少的张数

def minNumMoney(arr,aim):
    dp=[[0]*(aim+1) for i in range(len(arr))]
    for j in range(1,aim+1):
        if j%arr[0]==0:
            dp[0][j]=j/arr[0]
    for i in range(1,len(arr)):
        for j in range(1,aim+1):
            min=pow(2,32)-1
            f=0
            while j-f*arr[i]>0:
                if dp[i-1][j-f*arr[i]]!=0:
                    count=dp[i-1][j-f*arr[i]]+f
                    if min>count:
                        min=count
                f+=1
            if j-f*arr[i]==0:
                if min > f:
                    min=f
            if min!=pow(2,32)-1:
                dp[i][j]=min
    for i in dp:
        print i
    return dp[len(arr)-1][aim]
print minNumMoney([5,2,3],20)



#不允许重复
#给定数组arr,arr中所有的值都为正数且不重复。每个值代表一种面值的货币,再给定一个正数aim代表要找的钱数,求组成aim的最少货币数
''' arr=[5,2,3],aim=20
    返回-1
    arr=[5,2,3,5],aim=10
    返回2
    arr=[5,2,3,5],aim=15
    返回4
    arr=[5,2,3,5],aim=0
    返回4

'''#解法:arr长度为N,生成行数为N的,列数为aim+1的二维数组dp# ,dp[i][j]表示使用arr[0...i]的时候组成aim需要最少的张数

def minNumMoney(arr,aim):
    dp=[[0]*(aim+1) for i in range(len(arr))]
    for j in range(1,aim+1):
        if j==arr[0]:
            dp[0][j]=1
            break
    for i in range(1,len(arr)):
        for j in range(1,aim+1):
            min=pow(2,32)-1
            if dp[i-1][j-arr[i]]!=0:
                count=dp[i-1][j-arr[i]]+1
                if min>count:
                    min=count
            if j-arr[i]==0:
                min=1
            if min!=pow(2,32)-1:
                dp[i][j]=min
    for i in dp:
        print i
    return dp[len(arr)-1][aim]
print minNumMoney([5,2,2,4],4)

 

推荐阅读