零钱问题:
暴力递归:
递推关系:对arr[index]的使用的次数情况进行枚举,for(int i=0,arr[index]*i<=aim,i++),对于每一个i都对应一个枚举的情况,在该枚举情况下可以重新调整参数,此时可以使用的零钱数组是arr中index+1开始及之后的数组部分,新的目标值是aim=(aim-arr[index]*i),于是调用递归方法dp(arr,index+1,aim-arr[index]*i)即可返回当前枚举条件下的方案数目,对每一种情况下的方案数目进行累加即可得到总的方案数目。
边界条件:可以发现其实边界条件,就是思考什么时候满足拼凑,什么时候不能够实现拼凑,显然,当递归到aim=0时表名可以拼凑出目标值,当 aim小于0的时候表名该方法不能得到目标值,递归的边界条件就是当index==length时判断aim==0是否成立,若成立+1,否则+0
class Exchange:
def countWays(self, penny, n, aim):
if len(penny)<=0 or aim<0:
return 0
else:
return(self.pl(penny,0,aim))
def pl(self,arr,index,aim):
res= 0
if index == len(arr):
if aim == 0:
res = 1
else:
res = 0
else:
i = 0
while arr[index]*i<=aim:
res = res+self.pl(arr,index+1,aim-arr[index]*i)
i = i+1
return res
//测试代码
penny = [1,2,4]
n = 3
aim = 3
a = Exchange()
print(a.countWays(penny,n,aim))
记忆查找
# -*- coding: utf-8 -*-
class Exchange:
def countWays(self, penny, n, aim):
# write code here
if len(penny)<=0 or aim<0:
return 0
else:
dic = {}
for index in range(n+1):
for a in range(aim+1):
dic[(index,a)] = 0
#print('dic_ori=',dic)
return(self.pl(penny,0,aim,dic))
def pl(self,arr,index,aim,dic):
res= 0
if index == len(arr):
if aim == 0:
res = 1
else:
res = 0
else:
i = 0
value = 0
while arr[index]*i<=aim:
value = dic[(index+1,aim-arr[index]*i)]
if value!=0:
res = res+value
else:
res = res+self.pl(arr,index+1,aim-arr[index]*i,dic)
i = i+1
if res!=0:
dic[(index,aim)] = res
#print('dic=',dic)
return res
penny = [1,2,4]
n = 3
aim = 3
a = Exchange()
print(a.countWays(penny,n,aim))
动态规划
class Exchange:
def countWays(self, penny, n, aim):
# write code here
dic = {}
for i in range(n):
for j in range(aim+1):
dic[(i,j)] = 0
i=0
while penny[0]*i<=aim:
dic[(0,penny[0]*i)] = 1
i = i+1
for a in range(n):
dic[(a,0)] = 1
print('dic=',dic)
for i in range(1,n):
for j in range(1,aim+1):
if j>=penny[i]:
dic[(i,j)] = dic[(i-1,j)]+dic[(i,j-penny[i])]
else:
dic[(i,j)] = dic[(i-1,j)]
print(dic)
return dic[(n-1,aim)]
penny = [1,2,4]
n = 3
aim = 3
a = Exchange()
print(a.countWays(penny,n,aim))