问题描述:
用天平称重时,我们希望用尽可能少的砝码组合称出尽可能多的重量。如果有无限个砝码,但它们的重量分别是1,3,9,27,81,……等3的指数幂。神奇之处在于用它们的组合可以称出任意整数重量(砝码允许放在左右两个盘中)。本题目要求编程实现:对用户给定的重量,给出砝码组合方案,重量<1000000。要求程序输出的组合总是大数在前小数在后。可以假设用户的输入一定是一个大于0的整数。
例如:
用户输入:5,程序输出:9-3-1
用户输入:19,程序输出:27-9+1
思路分析:
1.将正整数转换为三进制数字,从低位到高位定位首次出现2的位置(如有),对应位加1转换为0(十进制加3的指数幂)。指数幂取负后相当于左托盘的砝码
2.得到的新整数重复上述操作。如此反复,直到三进制数字中不再含2。最终数字列表转换为3的指数幂,相当于右托盘的砝码
3.左右托盘砝码合并,按绝对值从大到小排序,带正负符号输出
例如:62转换为三进制2022,第一位加1(十进制加3的0次方,左托盘砝码:-1)得到63,转换为三进制2100,第四位加1(十进制加3的3次方,左托盘砝码:-27)得到90,转换为三进制10100(右托盘砝码:9、81),砝码组合:81-27+9-1
参考代码:
def ternary(num):
"""将十进制数字转换为从低位到高位排列的三进制数字列表"""
num_list = []
while num > 0:
num_list.append(num % 3)
num //= 3
return num_list
num = int(input("请输入物品重量:"))
group = [] #定义存储砝码组合的列表
num_list = ternary(num)
while 2 in num_list: #循环检查三进制数字列表中是否含2
num += pow(3, num_list.index(2)) #定位首次出现2的位置,对应位加1转换为0(十进制加3的指数幂)
group.append(-pow(3, num_list.index(2))) #将指数幂取负加入砝码组合(左托盘)
num_list = ternary(num)
#将最终不含2的数字列表转换为3的指数幂加入砝码组合(右托盘)
group.extend(pow(3, i) for i, v in enumerate(num_list) if v == 1)
group.sort(key = lambda x: abs(x), reverse = True) #按绝对值从大到小排序
print('砝码组合:', ''.join('%+d' %_ for _ in group).lstrip('+')) #带正负符号输出
运行结果:
请输入物品重量:2023
砝码组合: 2187-243+81-3+1