换钱的最少货币数

1.给定数组arr,arr中所有的值都是正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim代表要找的钱数,求组成aim的最少货币数。
方法一:
第一列都为0,第一行表示只能使用arr[0]货币的情况下找某个钱数的最小张数,之后的位置依次从左到右,再从上到下计算,比较dp[i-1][j]和dp[i][j-arr[0]]+1的值,选较小的,上一行的数是可以找开的张数。

#coding=utf-8

def solution(nums,aim):
    if len(nums)==0 or aim<0:
        return -1
    n=len(nums)
    m=float('Inf')
    dp=[[0 for i in range(aim+1)] for j in range(len(nums))]
    for i in range(1,aim+1):
        dp[0][i]=m
        if i-nums[0]>=0 and dp[0][i-nums[0]]!=m:
            dp[0][i]=dp[0][i-nums[0]]+1
    left=0
    for i in range(1,n):
        for j in range(1,aim+1):
            left=m
            if j-nums[i]>=0 and dp[i][j-nums[i]]!=m:
                left=dp[i][j-nums[i]]+1
            dp[i][j]=min(left,dp[i-1][j])
    if dp[n-1][aim]!=m:
        return dp[n-1][aim]
    else:
        return -1

方法二: 空间压缩法,参考矩阵的最小路径和

#coding=utf-8

class Solution(object):
    def coinChange(self,nums,aim):
        if len(nums)==0 or aim<0:
            return -1
        n=len(nums)
        m=float('Inf')
        dp=[0 for i in range(aim+1)]
        for i in range(1,aim+1):
            dp[i]=m
            if i-nums[0]>=0 and dp[i-nums[0]]!=m:
                dp[i]=dp[i-nums[0]]+1
        left=0
        for i in range(1,n):
            for j in range(1,aim+1):
                left=m
                if j-nums[i]>=0 and dp[j-nums[i]]!=m:
                    left=dp[j-nums[i]]+1
                dp[j]=min(left,dp[j])
        if dp[aim]!=m:
            return dp[aim]
        else:
            return -1
  1. 给定数组arr,arr中所有的值都为正数,每个值仅代表一张钱的面值,再给定一个整数aim代表要找的钱数,求组成aim的最少货币数。

直接是压缩空间以后的动态规划

#coding=utf-8

class Solution(object):
    def coinChange(self,nums,aim): 
        if len(nums)==0 or aim<0:
            return -1
        m=float('Inf')
        dp=[0 for i in range(aim+1)]
        for i in range(1,aim+1):
            dp[i]=m
        if nums[0]<=aim:
            dp[nums[0]]=1
        for i in range(1,len(nums)):
            for j in range(aim,0,-1):
                leftup=m
                if j-nums[i]>=0 and dp[j-nums[i]]!=m:
                    leftup=dp[j-nums[i]]+1
                dp[j]=min(leftup,dp[j])
        if dp[aim]!=m:
            return dp[aim]
        else:
            return -1

3.牛客上的题目
给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。
当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。
输入描述:

输入为两行:

第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)

第二行为n个正整数Ai,以空格隔开。

输出描述:

输出所求的方案数
示例1
输入

5 15
5 5 10 2 3
输出

4

#coding=utf-8

while True:
    try:
        f=map(int,raw_input().strip().split())
        A=map(int,raw_input().strip().split())
        n=f[0];target=f[1]
        res=[[0 for i in range(target+1)] for j in range(n)] 
        if A[0]<=target:
            res[0][A[0]]=1
        for i in range(1,n):
            for j in range(1,target+1):
                res[i][j]+=res[i-1][j]
                if j-A[i]>=1:
                    res[i][j]+=res[i-1][j-A[i]]
                if j==A[i]:
                    res[i][j]+=1
        print res[n-1][target]
    except:
        break
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值