算法高手必备:C++背包九讲终极模板

目录

🌟 背包问题核心思想

📌 0-1背包模板

🔄 完全背包模板

🎲 多重背包模板

🧩 混合背包模板

🌐 二维费用背包模板

🎯 恰好装满问题

📊 方案数统计模板

💡 关键总结


🌟 背包问题核心思想

状态定义dp[i][j] 表示前i个物品,在容量j的限制下获得的最大价值
核心方程dp[i][j] = max(选当前物品策略,不选策略)
空间优化:绝大多数情况可用一维数组倒序遍历实现


📌 0-1背包模板

特点:每个物品只能选0/1次
倒序遍历容量是关键!

vector<int> dp(bagSize + 1);
for(int i = 0; i < n; ++i){
    for(int j = bagSize; j >= weight[i]; --j){
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

🔄 完全背包模板

特点:物品无限次选取
正序遍历实现重复选择

vector<int> dp(bagSize + 1);
for(int i = 0; i < n; ++i){
    for(int j = weight[i]; j <= bagSize; ++j){
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

🎲 多重背包模板

特点:物品最多选k次 ▶️ 二进制优化版本

// 二进制拆分预处理
vector<int> new_weights, new_values;
for(auto &item : items){
    int cnt = item.max_count;
    for(int k=1; k<=cnt; k*=2){
        new_weights.push_back(item.weight * k);
        new_values.push_back(item.value * k);
        cnt -= k;
    }
    if(cnt > 0){
        new_weights.push_back(item.weight * cnt);
        new_values.push_back(item.value * cnt);
    }
}

// 0-1背包过程(略)

🧩 混合背包模板

特点:0-1/完全/多重混合 ▶️ 类型判断+分支处理

for(每个物品){
    if(0-1背包类型)
        倒序遍历容量
    else if(完全背包)
        正序遍历容量
    else if(多重背包)
        二进制拆分后按0-1处理
}

🌐 二维费用背包模板

特点:同时限制重量/体积两个维度

vector<vector<int>> dp(weightSize+1, vector<int>(volumeSize+1));
for(int i=0; i<n; ++i){
    for(int j=weightSize; j>=weight[i]; --j){
        for(int k=volumeSize; k>=volume[i]; --k){
            dp[j][k] = max(dp[j][k], 
                          dp[j-weight[i]][k-volume[i]] + value[i]);
        }
    }
}

🎯 恰好装满问题

初始化技巧

dp[0] = 0;          // 初始状态合法
for(int i=1; i<=bagSize; ++i) 
    dp[i] = -INF;   // 非法状态

📊 方案数统计模板

递推式dp[j] += dp[j - weight[i]]

vector<int> dp(bagSize+1, 0);
dp[0] = 1; // 初始方案数
for(int i=0; i<n; ++i){
    for(int j=bagSize; j>=weight[i]; --j){
        dp[j] += dp[j - weight[i]];
    }
}

💡 关键总结

  1. 遍历顺序定乾坤:0-1背包倒序,完全背包正序

  2. 状态初始化:普通问题初始化0,恰好装满需特殊处理

  3. 复杂度控制:多重背包必须二进制优化

  4. 维度扩展:二维费用只需增加状态维度


🚀 掌握这些模板,LeetCode背包问题直接默写!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值