设有n 种不同面值的硬币,每个硬币的面值存于数组$T[1:n]$中。现在用这些硬币来找钱。各种硬币使用的个数不限。设计一个动态规划算法以计算找出钱m 时,所用的硬币的最小个数C。

def change_money(T,m):
    T.sort()                             # 保证面额单调递增
    n=len(T)
    C=[[0]*(m+1) for i in range(n)]      # j=m时找的钱为m,因此初始化到m+1大小
    for j in range(m+1):
        if j%T[0]==0:
            C[0][j] = j//T[0]            # 边界条件,只用最小面额的硬币
        else:
            C[0][j] = float('inf')       # 最小面额硬币无法找钱时,不可能找钱
    for i in range(1,n):
        for j in range(1,m+1):
            plans = []
            for k in range(j//T[i]+1):   # k 是要用新的面额硬币的个数
                plans.append(C[i-1][j-k*T[i]]+k)   # 去掉用大额硬币的金额,剩下的金额找钱
            C[i][j]=min(plans)           # 在不同k值的方案中选最优
    return C[n-1][m]

设计一个动态规划算法从n 个数构成的数列中找出最长单调递增子序列。

def LCS(X,Y):
    # 使用最长公共子序列算法求解
    n = len(X)
    m = len(Y)
    C=[[0]*m for i in range(n)]
    B=[['']*n for i in range(n)]
    for i in range(1,n):
        for j in range(1,m):
            if X[i]==Y[j]:
                C[i][j]=C[i-1][j-1]+1
                B[i][j]="ul"
            elif C[i-1][j]>=C[i][j-1]:
                C[i][j]=C[i-1][j]
                B[i][j]="up"
            else:
                C[i][j]=C[i][j-1]
                B[i][j]="left"
    return B,C
def print_subsequence(B,X,i,j,ans):
    if i==0 or j==0:
        return
    if B[i][j]=="ul":
        print_subsequence(B,X,i-1,j-1,ans)
        ans.append(X[i])
    elif B[i][j]=="up":
        print_subsequence(B,X,i-1,j,ans)
    else:
        print_subsequence(B,X,i,j-1,ans)

def longest_subsequence(X):
    # X[0]恒为0,不表示序列元素
    B,C=LCS(X,[0]+sorted(X[1:]))
    ans=[]
    print_subsequence(B,X,len(X)-1,len(X)-1,ans)
    return ans

标签: none

评论已关闭