算法之Python实现 - 003 : 换钱的方法数

【题目】给定数组arr,arr中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim代表要找的钱数,求组成aim的方法数。

【代码1】递归

import numpy as np

def changemeans(arr,aim):
    if len(arr)<0:
        print("No coin provided for change!")
    arr.sort()
    arr.reverse()
    m = process(arr,0,aim)
    print('There are ',m,' ways!')

def process(arr,idx,aim):
    res = 0
    i = 0
    if aim == 0:
        res = 1
    else :
        if idx == len(arr):
            res = 0
        else :
            while arr[idx]*i <= aim:
                res += process(arr,idx+1,aim - arr[idx]*i)
                i += 1
    return res
        
    
# ===CALL === #
a = [5,10,25,1]
tar = 1000
changemeans(a,tar)    

【代码2】改进递归(递归加入记忆搜索)

  【原理】:例如按照题目中的a = [5,10,25,1],使用a[0]和a[1],利用[25,1]组成剩余的980元的可能性就是一种重复递归,假设利用[25,1]组成剩余的980元需要5秒钟,那么【代码1】需要搜索5*0+10*2,5*2+10*1,5*5 三次递归,【代码2】额外耗用了O((N+1)*(aim+1))的空间,但是只要三次寻址即可。

import numpy as np

def changemeans(arr,aim):
    if len(arr)<0:
        print("No coin provided for change!")
    arr.sort()
    arr.reverse()
    map = np.zeros((len(arr)+1,aim+1))
    m = process(arr,0,aim,map)
    print('There are ',m,' ways!')

def process(arr,idx,aim,map):
    res = 0
    i = 0
    if aim == 0:
        res = 1
    else :
        if idx == len(arr):
            res = 0
        else :     
            while arr[idx]*i <= aim:
                mapval = map[idx+1][aim- arr[idx]*i]
                if mapval != 0:
                    if mapval == -1:    mapval = 0
                    res += mapval
                else:   
                    res += process(arr,idx+1,aim - arr[idx]*i,map)
                i += 1
    if res == 0:
        map[idx][aim] = -1
    else :
        map[idx][aim] = res
    #print(':',int(map[idx][aim]),res)
    return res
        
    
# ===CALL === #
a = [5,10,25,1]
tar = 1000
changemeans(a,tar)    

猜你喜欢

转载自www.cnblogs.com/ElfoDigger/p/10608551.html
003
今日推荐