0
点赞
收藏
分享

微信扫一扫

蓝桥杯 算法训练 无聊的逗 Python 100分

small_Sun 2022-02-03 阅读 105

典型的背包问题,用一个二维矩阵来记录状态

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出来

满分结束

举报

相关推荐

0 条评论