典型的背包问题,用一个二维矩阵来记录状态
n = int(input())
sticks = list(map(int, input().split()))
volumn = sum(sticks) // 2 + 1
# 背包的容积
res_map = [[-1 for _ in range(n + 1)] for _ in range(volumn)]
res_map[0][0] = 0
用第一个维度索引记录“最长棒” - “次长棒”,第二个维度索引记录“已经考虑前n个木棍”,对应单元格记录“最长棒”与“次长棒”等长部分的长度
背包容积这么设定的原因是:要组合出等长棒,所以“最长棒” - “次长棒” <= sum(sticks) // 2
每次把木棍加入考虑范围时,可选择:
1. 不与“最长棒”、“次长棒”叠加
2. 与“最长棒”叠加
3. 与“次长棒”叠加
4. 与“次长棒”叠加,“次长棒”变为“最长棒”,“最长棒”变为“次长棒”
for idx in range(1, n + 1):
# 把第idx个木棍加入考虑范围
for res in range(volumn):
stick = sticks[idx - 1]
res_map[res][idx] = res_map[res][idx - 1]
# 不与”最长棒”、“次长棒”叠加,直接传递状态
last_state = res - stick
# 找到可供传递的状态
if last_state >= 0:
# 判断状态合法
last_value = res_map[last_state][idx - 1]
if last_value >= 0:
res_map[res][idx] = last_value
# 与“最长棒”叠加,等长部分不变
last_state = res + stick
if last_state < volumn:
last_value = res_map[last_state][idx - 1]
if last_value >= 0:
res_map[res][idx] = max([res_map[res][idx], last_value + stick])
# 与“次长棒”叠加,等长部分改变 ———— 比较取最优
last_state = stick - res
if last_state >= 0:
last_value = res_map[last_state][idx - 1]
if last_value >= 0:
res_map[res][idx] = max([res_map[res][idx], last_value + stick - res])
# 与“次长棒”叠加,“次长棒”变为“最长棒”,“最长棒”变为“次长棒”,等长部分改变 ———— 比较取最优
最终结果是“最长棒” - “次长棒” = 0,且考虑了所有的木棍,对应res_map[0][-1],print出来
满分结束