使用Python完成凑零钱问题(dfs思想)
题目描述
韩梅梅喜欢满宇宙到处逛街。现在她逛到了一家火星店里,发现这家店有个特别的规矩:你可以用任何星球的硬币付钱,但是绝不找零,当然也不能欠债。韩梅梅手边有
1
0
4
10^4
104枚来自各个星球的硬币,需要请你帮她盘算一下,是否可能精确凑出要付的款额。
输入格式:
输入第一行给出两个正整数:N(
≤
1
0
4
≤10^4
≤104)是硬币的总个数,M(
≤
1
0
2
≤10^2
≤102)是韩梅梅要付的款额。第二行给出 N 枚硬币的正整数面值。数字间以空格分隔。
输出格式:
在一行中输出硬币的面值 V1≤V2≤⋯≤Vk,满足条件 V1+V2+…+Vk=M。数字间以 1 个空格分隔,行首尾不得有多余空格。若解不唯一,则输出最小序列。若无解,则输出 No Solution。
注:我们说序列{ A[1],A[2],⋯ }比{ B[1],B[2],⋯ }“小”,是指存在 k≥1 使得 A[i]=B[i] 对所有 i<k 成立,并且 A[k]<B[k]。
输入样例1:
8 9
5 9 8 7 2 3 4 1
输出样例1:
1 3 5
输入样例2:
4 8
7 2 4 3
输出样例1:
No Solution
题目分析:
根据题目给出的问题,首先想到用DFS思想,遍历整个数组,依次相加找到符合的答案,但这样可能会有多组答案,题目要求最小序列,那么首先可以将输入的金额由小到大排序,这样遍历出来的序列就是最小序列。(PS:后来分析之后考虑到使用新学的动态规划思想也能解决该问题。)
题目中关键的一个检测点就是当所有的数额相加之后小于要求的数额时,要退出返回,不用去执行递归。
代码实现
import numpy
N,M = input().split(" ")
M = int(M)
N = int(N)
f = 0
temp = 0
p = 0
arr = [0]*N
str= input().split(" ")
for i in str:
arr[p] = int(i)
p+=1
answer = numpy.array([0]*N)
def dfs(pos,sum):
global temp, f
if sum > M:
return
if sum == M:
f = 1
for i in range(0,temp):
if i == temp-1:
print(answer[i])
else:
print(answer[i],"",end="") ##按题目要求输出为一行,所以使用end=“”,取消每次输出默认的换行符
return
for m in range(pos,N):
answer[temp] = arr[m]
temp+=1
dfs(m+1,sum+arr[m])
if f:
break
temp-=1
sum = 0
for i in range(0,N):
sum+=arr[i]
if sum < M:
print("No Solution")
else:
arr = sorted(arr,reverse=False)
dfs(0,0)
if not f:
print("No Solution")
exit(0)
知识点汇总:
- 排序函数:python3自带排序函数sorted(),参数reverse=false时为升序,为true时为降序。
- 满足题目需求的从一行输入数据,以空格隔开,单独使用input是不行的,可以使用str= input().split(" “) 将输入的输出按输入格式存到字符串变量中,然后用for循环放入list中,也可以使用map()方法:list(map(int,input().split(” ")))方法完成用空格隔开的一行输入,map方法返回的为map对象,想要获取列表对象就用list(map())即可。