伐木工(200)
- 一根X米长的树木,切成不同长度(均为整数)的木材后进行交易,也可整根树木交易;
- 交易的价格为每根木头段长度(即木头段最大价值)之积(如切割为a, b, c段,收益为abc),若未切割则收益为X*1;
- 如何尽量少的切割,使收益最大化?
输入描述:
木材的长度X<=50
输出描述:
最优收益时,各个树木段的长度,升序排序,以空格分割
示例1
输入:
10
输出:
3 3 4
说明:
一根2米长的树木,不需要切割,最大收益为2;
一根4米长的树木,不需要切割,最大收益为4;
一根5米长的树木,切割为2,3,最大收益为6;
一根10米长的树木,切割为3,4,3,也可切为3,2,2,3,只不过同样的收益多切了一次,增加成本;
思路:
- 贪心算法,大化小,大问题依赖小问题的最优解;
- 根据题意可知,当树木长度为1、2、3、4 时,不用切割就可以获取最大价值,当树木长度更大时,依次从长度为1开始求最优解,例如长度从1 -> 10的树木各自的最大价值及分段可以表示为如下:
- max_price [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],长度为 i 的树木可卖的最大价值为 i
- pies = [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10]],长度为 i 的树木获取最大价值时的分段
其他方案:
# 树木的长度
total_len = int(input().strip())
# 默认的最大价值
max_price = [i for i in range(total_len + 1)]
# 长度为i的树木 在获取最大价值时的分段
pies = [[i] for i in range(total_len + 1)] # i = 1,2,3,4 时 是不用分段的
# 从最小的问题开始求解,直到达到目标的大问题
i = 1
while i <= total_len:
# 对当前长度为i的树木 进行分段
for j in range(1, i): # j 为第一段, k 为另一段
k = i - j
if max_price[i] > max_price[j] * max_price[k]: # 分段之积 j*k 实际上是max_price[j] * max_price[k]
continue
# 更新最大价值
elif max_prce[i] < max_price[j] * max_price[k]:
max_price[i] = max_price[j] * max_price[k]
pies[i] = []
for a in range(len(pies[j])):
pies[i].append(pies[j][a])
for a in range(len(pies[k])):
pies[i].append(pies[k][a])
else: # 等价值时,取最少的分段
if len(pies[i]) > len(pies[j]) + len(pies[k]):
pies[i] = []
for a in range(len(pies[j])):
pies[i].append(pies[j][a])
for a in range(len(pies[k])):
pies[i].append(pies[k][a])
i+=1
result = pies[total_len]
result.sort()
output_str = ""
for i in range(len(result)):
output_str += str(result[i]) + " "
print(output_str)