• python 背包问题:0-1背包,多重背包,数据结构,超详细模板套用和解读;数组组合问题


    一、0-1背包问题

    题目:有n个物品,第i个体积为w[i],价值为v[i],每个物品最多选一个,求体积和不超过capacity时能装物品的最大价值

    转移方程:

    dfs(i,c) = max(dfs(i-1,c),dfs(i-1,c-w[i])+v[i])

    含义:第i个物品的最大价值等于,(没有选择第i个物品时的价值)和(选择了第i个物品时的价值)中最大的哪一个。

    1. def zero_one_knapsack(weight:List[int],value:List[int],capacity:int)->int:
    2. n = len(weight)
    3. def dfs(i,c):
    4. if i < 0:
    5. return 0
    6. if c < weight[i]:
    7. return dfs(i-1,c)
    8. return max(dfs(i-1,c),dfs(i-1,c-weight[i])+value[i])
    9. ans = dfs(n-1,capacity)
    10. return ans
    11. weight = [1,3,5,6,7,8]
    12. value = [5,4,3,2,1,1]
    13. capacity = 10
    14. print(zero_one_knapsack(weight,value,capacity))

    (1)求最大价值:如上

    (2)求方案数:需要更改约束条件和方程:

    1. def dfs(i,c):
    2. if i < 0:
    3. return 1 if c==0 else 0
    4. if weight[i] < c:
    5. return dfs(i-1,c)
    6. return dfs(i-1,c) + dfs(i-1,c-weight[i])

    方案数:数组递推形式:此时没有用到value数组:此种题目常见于数组组合达到target值的方案数

    1. def zero_one_knapsack(weight:List[int],capacity:int)->int:
    2. n = len(weight)
    3. f = [[0] * (capacity + 1) for _ in range(n + 1)]
    4. f[0][0] = 1
    5. for i,x in enumerate(weight):
    6. for c in range(capacity + 1):
    7. if c < x:
    8. f[i+1][c] = f[i][c]
    9. else:
    10. f[i+1][c] = f[i][c] + f[i][c-x]
    11. return f[n][capacity]
    12. weight = [1,3,5,6,7,8]
    13. capacity = 10
    14. print(zero_one_knapsack(weight,capacity))

    空间优化:用二维矩阵表示

    1. def zero_one_knapsack(weight:List[int],capacity:int)->int:
    2. n = len(weight)
    3. f = [[0] * (capacity + 1) for _ in range(2)]
    4. f[0][0] = 1
    5. for i,x in enumerate(weight):
    6. for c in range(capacity + 1):
    7. if c < x:
    8. f[(i+1)%2][c] = f[i%2][c]
    9. else:
    10. f[(i+1)%2][c] = f[i%2][c] + f[i%2][c-x]
    11. return f[n%2][capacity]

    空间优化:用一维矩阵表示

    1. def zero_one_knapsack(weight:List[int],capacity:int)->int:
    2. n = len(weight)
    3. f = [0] * (capacity + 1)
    4. f[0] = 1
    5. for x in weight:
    6. for c in range(capacity,x-1,-1):
    7. f[c] = f[c] + f[c-x]
    8. return f[capacity]

    二、多重背包:就是不限制物品数量,同一个物品可以拿多次

    转移方程:

    dfs(i,c) = max(dfs(i-1,c),dfs(i,c-w[i])+v[i])

    就是拿完i物品,还可以继续拿i,而不是递到i-1。

    1. def dfs(i,c):
    2. if i < 0:
    3. return 0
    4. if c < w[i]:
    5. return dfs(i-1,c)
    6. return max(dfs(i-1,c),dfs(i,c-w[i])+v[i])

  • 相关阅读:
    Linux上的监控工具:Zabbix、Prometheus、APM和ELK
    SpringMVC自定义视图完成步骤 和 视图解析的源码剖析
    使用Apache ECharts同时绘制多个统计图表
    通用任务批次程序模板
    mysql数据库安装
    Python编程相关的书籍
    衡量算法的性能-时空复杂度分析
    并查集 力扣990等式方程的可满足性
    网络安全(黑客技术)—2024自学笔记
    每天记录学习的新知识:RxJava2 操作符
  • 原文地址:https://blog.csdn.net/L_goodboy/article/details/130899148