2022“杭电杯”中国大学生算法设计超级联赛(1)1003 Backpack个人题解

这是一篇关于动态规划和位运算的编程题解析,讲述了如何解决在01背包基础上扩展的问题,寻找使得所有物品体积之和为给定值m且异或和最大的方案。通过使用bitset优化状态转移方程,将三维动态规划转化为二维,最终找到异或和最大值。
摘要由CSDN通过智能技术生成

Backpack

题目描述

有n件物品,他们各自都有体积vi和价值wi,给你一个体积为m的背包,求是否能从这n件物品中取出若干件,使得它们的体积之和恰好为m,所有物品的异或和最大,最大值是多少

分析

这道题是在01背包的基础上的扩展,其中n,m满足 1≤n,m<210,vi,wi 满足 1≤vi,wi<210 ,我们可以用f[i] [j] [k] 表示在前i个物品中选出若干件,异或和为j,体积为k的方案是否存在,那么,我们可以将状态划分为:
①取第i件物品,f[i] [j] [k] = f[i - 1] [j ⊕ w] [k - v]
为什么是j ⊕ w呢?
因为如果取了第i件物品,那么异或和就变成了j ⊕ w ⊕ w = j,体积变成了k - v + v = k,所以这种情况下 f[i] [j] [k] = f[i - 1] [j ⊕ w] [k - v]
②没有取第i件物品,f[i] [j] [k] = f[i - 1] [j] [k]
所以最终状态转移方程为:f[i] [j] [k] = f[i - 1] [j ⊕ w] [k - v] | f[i - 1] [j] [k]

这样的话就是三维,由于题目中给的所有数值都是小于1024的,我们可以用bitset优化成二维 ,用f[i] [j]表示异或值为i,体积为j的方案是否存在

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1050;
int n,m;
bitset<N> f[N],g[N];

void solve()
{
    for(int i = 0;i < 1024;i ++){
        f[i].reset();
        g[i].reset();
    }
    f[0][0] = 1;//初始化,异或和为0,体积为0的方案是存在的
    cin >> n >> m;
    for(int i = 1;i <= n;i ++){
        int v,w;
        cin >> v >> w;
        for(int j = 0;j < 1024;j ++){
            g[j] = f[j];//用g[]来记录上一次的状态
            g[j] <<= v;//为什么是左移v位呢?这一步表示当异或和为j时,
            //取第j件物品,将g[j]左移v位,最终如果存在左移m位的方案时,
            //就说明存在使得所有物品体积和为m的方案,即如果存在f[i][m] == 1时,
            //就说明存在异或和为i,取得的所有物品体积和为m的方案
        }
        for(int j = 0;j < 1024;j ++){
            f[j] |= g[j ^ w];//取当前这件物品,就是g[j ^ w],不取这件物品就是f[j]
        }
    }
    int ans = -1;
    for(int i = 0;i < 1024;i ++){
        if(f[i][m]) ans = i;
    }
    cout << ans << '\n';
}

int main()
{
    int t;
    cin >> t;
    while (t --){
        solve();
    }
    return 0;
}

大家如果有不懂的地方欢迎在评论区留言~
创作不易,留下你的赞叭~

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王超能吃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值