【专题讲解】背包问题

这篇博客详细讲解了背包问题的各种类型,包括01背包、完全背包、多重背包、分组背包、混合背包问题、二维费用背包问题等。还讨论了背包问题的方案数求解、最优方案数求解以及有依赖的背包问题。文中提供了问题的特征、状态转移方程和优化策略,并给出了部分问题的解题思路。
摘要由CSDN通过智能技术生成

引言

背包问题可以分为:

  1. 01背包 (空间优化:倒序)
  2. 完全背包 (空间优化:正序)
  3. 多重背包及其优化(化为01背包,最低复杂度 O ( N Σ log ⁡ 2 ( K ) ) O(N\Sigma \log_2(K)) O(NΣlog2(K))

以及一些变种的问题:

  1. 分组背包
  2. 混合背包问题
  3. 二维费用背包问题
  4. 背包问题求方案数
  5. 背包问题求最优方案数
  6. 背包问题求具体的方案
  7. 有依赖的背包问题
  8. 大于某个限度的方案数量

01背包

有 N 件物品和一个容量是 V的背包。每件物品只能使用一次。第 i 件物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。

特点:每个物品的数量只有一个。
状态:dp[i][j]考虑前 i 个物品,空间为 j

  • 没有进行优化:第二层循环正序dp[i][j] = max(dp[i-1][j], dp[i-1][j-vi]+wi)
  • 进行优化:第二层倒序dp[j] = max(dp[j], dp[j-vi]+wi)
    在这里插入图片描述
## 未进行优化
n, v = map(int, input().split())
dp = [[0]*(v+1) for _ in range(n+1)]
for i in range(1, n+1):
	a,b = map(int, input().split())
    for j in range(1,v+1):
    # 分别考虑,大于体积和不大于
        if j>=a:
            dp[i][j] = max(dp[i-1][j], dp[i-1][j-a]+b)
        else:
            dp[i][j] = dp[i-1][j]
print(dp[n][v])

## 进行状态压缩的优化
n, v = map(int, input().split())
dp = [0]*(v+1)
for i in range(n):
    a,b = map(int, input().split())
    for j in range(v, a-1, -1):
        dp[j] = max(dp[j], dp[j-a]+b)
print(dp[v]) 

完全背包

背包中每种物品的个数是无穷多的,可以重复拿。

需要考虑优化:
f[i , j ] = max( f[i-1,j] , f[i-1,j-v]+w , f[i-1,j-2*v]+2*w , f[i-1,j-3*v]+3*w , .....)
f[i , j-v]= max( f[i-1,j-v] , f[i-1,j-2*v] + w , f[i-1,j-2*v]+2*w , .....)
由上两式,可得出如下递推关系:
f[i][j]=max(f[i,j-v]+w , f[i-1][j])

  • 未进行空间优化:dp[i][j] = max(dp[i-1][j], dp[i][j-vi]+wi) 注意后一项是dp[i]转移的。
  • 进行空间优化:第二层正序dp[j] = max(dp[j], dp[j-vi]+wi)
n, v = map(int, input().split())
# 未进行状态压缩 
dp = [[0]*(v+1) for _ in range(n+1)]
for i in range(1,n+1):
    a, b = map(int, input().split())
    for j in range(1, v+1):
        if j >= a:
            # 注意这里于01背包不同,这里是从DP[i][j-k]转移
            dp[i][j] = max(dp[i-1][j], dp[i][j-a] + b)
        else:
            dp[i][j] = dp[i-1][j]
print(dp[n][v])

# 进行状态压缩
dp = [0]*(v+1)
for i in range(n):
    a, b = map(int, input().split())
    for j in range(a,v+1):
        dp[j] = max(dp[j], dp[j-a]+b)
print(dp[v])
import java.util.*;
public class Main{
   
    public static void main(String[] args){
   
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[] v = new int[n];
        int[] w = new int[n];
        for(int i 
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值