【问题描述】
小蓝最近迷上了用火柴棒拼数字字符, 方法如下图所示:
他只能拼 0 至 9 这十种数字字符, 其中每个数字字符需要的火柴棒的数目依次是: 6,2,5,5,4,5,6,3,7,6。他不喜欢重复拼同一个数字字符, 所以对于每个数字字符他最多拼十个。小蓝会把拼出来的数字字符组合在一起形成一个整数, 例如对于整数 345 , 需要的火柴棒的数目为 5+4+5=14 根。小蓝有 300 根 火柴棒, 他想知道自己能拼出的最大整数是多少? 可以不使用完这 300 根火柴 棒, 可以有多余的火柴棒剩下。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个由大写字母组成的字符串,在提交答案时只填写这个字符串,填写多余的内容将无法得分。
我们看题目可以很清楚这是一个多重背包问题 ,我在网上发现没有python相关的解答,所以特意来做一个记录。但是不同于一般的多重背包问题,这里的火柴数字没有价值,或者说价值不明确,所以直接dp最大数字。每多拼一个火柴数字就多一个数量级,所以要尽可能多的拼数字。一般的加法不适用这种情况,用字符串相加,将其一般化。所以所以状态转移方程为:
dp[j] = max(dp[j],eval(str(i-1)*k+str(dp[j-k*w[i]])))
其余同一般多重背包问题,完整代码如下:
w = [0,6,2,5,5,4,5,6,3,7,6]
dp = [0 for _ in range(301)] #初始化dp列表
for i in range(1,11): #前i件物品
for j in range(300,w[i]-1,-1): #重量限制,逆向枚举
for k in range(11):
if j-k*w[i]>=0:
dp[j] = max(dp[j],eval(str(i-1)*k+str(dp[j-k*w[i]])))
print(max(dp)//10)
#这里整除10是因为dp列表初始化为0,在字符化相加的时候多加一个'0',输出结果的时候应该去掉。
【最终结果】
9999999999777777777755555555554444444444333333333322222222221111111111