使用场景
- 有一些报销额度,需要用自己发票的金额去抵扣;
- 如果发票金额总和超过报销额度,只能报销最大额度的金额;
比如:报销额度1000,发票金额1200,那么可以报销1000 - 现在的发票也可以留给下次报,所以你需要凑出符合额度的发票,但不想让金额超出太多;
- 此程序效率低,但你的时间比CPU的时间值钱很多。
Yaodo·2021-04-29·465 次阅读
from itertools import combinations intro = """==================================== ===@凑发票计算器 ===@Yaodo ===@https://www.imtrq.com ==================================== """ print(intro) s = input("输入现有的每张发票金额,以空格键分隔,按回车键结束:\n") target = float(input("输入目标金额,按回车键结束:\n")) li = [float(x) for x in s.split()] # 最多需要多少张发票 def get_max_num(li, target): li.sort() for n in range(1, len(li)+1): if sum(li[:n]) >= target: return n return 0 # 最少需要多少张发票 def get_min_num(li, target): li.sort(reverse=True) for n in range(1, len(li)+1): if sum(li[:n]) >= target: return n return 0 # 如果选择n张发票,返回金额最接近的组合 def try_a_num(n, li, target): comb = list(combinations(li, n)) answer = [] for i in comb: if sum(i)>=target: answer.append((sum(i), len(i), i)) if len(answer)==0: return (0,0,0) else: answer.sort() return answer[0] # 每个n试一次 def work(li, target): max_num = get_max_num(li, target) min_num = get_min_num(li, target) if max_num*min_num==0: return 0 answer = [] for n in range(min_num, max_num+1): answer.append(try_a_num(n, li, target)) return answer # 输出结果 answer = work(li, target) if answer==0 or answer==[]: print("错误!无法凑出所需金额。") else: print("\n====================================\n方案列表\n====================================") answer.sort() i = 1 for x in answer: output = '{}\t总金额:{:.2f}\t发票张数:{}\t组合:{}'.format(i, x[0], x[1], x[2]) print(output) i+=1
Comments | 1 条评论
博主 ǝɔ∀ǝdʎz∀ɹɔ
哈哈!好有趣!