题目链接:Problem - 7140

 样例输入:

1
5 4
2 4
1 6
2 2
2 12
1 14

样例输出:

14

 题意:

有n个物品,每个物品体积为v[i],价值为w[i]

求是否存在一种取法使得总体积为m,若存在求出最大的异或和

题解:

显然01背包。

一:将异或和放入背包中维护,即多开一维来表示

状态表示:bool  dp[i][j][k]:前i个物品,异或和为j,体积为k,是否存在

转移方程:

dp[i][j][k] = dp[i][j][k]                                    (k<v[i])

dp[i][j][k] = dp[i][j][k] | dp[i][ j^w[i] ][ k-v[i] ]  (k>=v[i])

​
​bool dp[N][N][N];
dp[0][0][0] = 1;//初始化for (int i = 1; i <= n; i++)for (int j = 0; j < 1024; j++)for (int k = 0; k <= m; k++){dp[i][j][k] = dp[i - 1][j][k]; //不取if (k >= v[i])dp[i][j][k] |= dp[i - 1][j ^ w[i]][k - v[i]]; //取}int ans = -1;for (int j = 0; j < 1024; j++)if (dp[n][j][m])ans = j;cout << ans << endl;​​

二、通过01背包的空间优化可用两维表示:

状态表示:bool  dp[j][k]:前i个物品,异或和为j,体积为k,是否存在

转移方程:

dp[j][k] = dp[j][k]                                 (k<v[i])

dp[j][k] = dp[j][k] | dp[ j^w[i] ][ k-v[i] ]  (k>=v[i])

​
​bool dp[N][N][N];
dp[0][0] = 1;//初始化for (int i = 1; i <= n; i++)for (int j = 0; j < 1024; j++)for (int k = m; k >= 0; k--){dp[j][k] = dp[j][k]; //不取if (k >= v[i])dp[j][k] |= dp[j ^ w[i]][k - v[i]]; //取}int ans = -1;for (int j = 0; j < 1024; j++)if (dp[j][m])ans = j;cout << ans << endl;

空间复杂度ok了,但是时间复杂度还是O(n^3),还是不够的,那么怎么优化呢?

三、bitset优化:

考虑到bitset的按位或运算(|)是对每一位进行或运算,将体积用bitset来表示,可通过一次的位运算将所有体积维度更新,故:

状态表示:bitset<N>dp[i][j]:前i个物品异或和为j,dp[i][j]第k位代表异或和为j体积为k是否存在

状态转移:

dp[i][j] = dp[i][j]                                   (k<v[i])

dp[i][j] = dp[i][j] | dp[ i ][ j^w[i] ]<<v[i]  (k>=v[i])

tips: 为什么左移v[i]呢?dp[ i ][ j^w[i] ]<<v[i]表示拿了这个物品,需要从体积k-w[i]转移过来,也就相当于dp[i][j]的第k位需要从dp[i][ j^w[i] ]的第k-v[i]位转移过来,所以需要将dp[ i ][ j^w[i] ]左移v[i]位。

​bitset<N>dp[N][N];
dp[0][0][0] = 1;                        //初始化for (int i = 1; i <= n; i++){for (int j = 0; j < 1024; j++){dp[i][j] = dp[i - 1][j ^ w[i]] << v[i] | dp[i - 1][j]; //转移方程,取/不取}}int ans = -1;for (int i = 0; i < 1024; i++)if (dp[n][i][m])ans = i;cout << ans << "\n";

可是这样空间复杂度右不行了,考虑

四:滚动数组进行优化:

状态表示:bitset<N>dp[2][j]:前i个物品异或和为j,dp[i][j]第k位代表异或和为j体积为k是否存在

状态转移:

dp[x][j] = dp[x^1][j]                                       (k<v[i])

dp[x][j] = dp[x^1][j] | dp[ x^1 ][ j^w[i] ]<<v[i]  (k>=v[i])

最后答案为dp[n&1][j]的第m位为1的异或和(j)的最大值。

详见代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
const int N = 1050;
int v[N], w[N];
bitset<N> dp[2][N]; // dp[i][j],i->滚动数组,j->异或和,bitset每一位的当前数位代表体积,对应值0/1代表是否存在
void solve()
{int n, m;cin >> n >> m;for (int i = 1; i <= n; i++) //读入cin >> v[i] >> w[i];for (int i = 0; i < 1024; i++)dp[0][i].reset(), dp[1][i].reset();     //重置为0dp[0][0][0] = 1;                            //初始化for (int i = 1, x = 1; i <= n; i++, x ^= 1) // i->前i个物品,x->滚动数组{for (int j = 0; j < 1024; j++) // j->异或和{dp[x][j] = dp[x ^ 1][j ^ w[i]] << v[i] | dp[x ^ 1][j]; //转移方程,取/不取}}int ans = -1;for (int i = 0; i < 1024; i++)if (dp[n & 1][i][m])ans = i;cout << ans << "\n";
}
signed main()
{// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);int T;cin >> T;for (int i = 1; i <= T; i++)solve();
}

2022“杭电杯”中国大学生算法设计超级联赛(1)C.Backpack相关推荐

  1. 2022“杭电杯”中国大学生算法设计超级联赛(8)

    2022"杭电杯"中国大学生算法设计超级联赛(8) [题目链接](Search Result (hdu.edu.cn)) D Quel'Thalas 题目大意 在二维平面上,[0, ...

  2. 2022“杭电杯”中国大学生算法设计超级联赛(4)

    2022"杭电杯"中国大学生算法设计超级联赛(4) [题目链接](Search Result (hdu.edu.cn)) D Link with Equilateral Trian ...

  3. 2022“杭电杯”中国大学生算法设计超级联赛 (1) 杭电多校第一场 2 3 4 5 8 12

    题目 1002 Dragon slayer 标程 1003 Backpack AC代码 1004 Ball AC代码 1008 Path AC代码 1009 Laser AC代码 1012 Alice ...

  4. 2022“杭电杯”中国大学生算法设计超级联赛 (2) 杭电多校第二场

    题目 1001 Static Query on Tree AC代码 1002 C++ to Python AC代码 1003 Copy AC代码 1005 Slayers Come AC代码 1007 ...

  5. 2022“杭电杯”中国大学生算法设计超级联赛(8)题解报告

    Problem D. Quel'Thalas 题解: 手玩一下就会发现答案是就是2n. 代码: #include<iostream> #include<algorithm> # ...

  6. 2022“杭电杯”中国大学生算法设计超级联赛(6)题解报告

    1006.Maex 题意: 给定一棵由从 1 到 n 编号的 n 个顶点组成的有根树,根为顶点 1.顶点 i 有一个自然数权重 ai,并且没有两个不同的顶点具有相同的权重.bu是以u为根的子树的权重的 ...

  7. 2022“杭电杯”中国大学生算法设计超级联赛(2)1003.Copy

    样例输入: 1 5 3 1 2 3 4 5 2 4 1 2 4 2 5 样例输出: 6  题意: 有q次操作,有以下两种: 1.选择区间[l,r],复制[l,r]追加到r后,总的数组的大小(n)不变 ...

  8. 2022“杭电杯”中国大学生算法设计超级联赛(8)补题

    1004  Quel'Thalas 题意 在二维平面上,点在坐标在[0,n]的区间内,通过添加无限长的直线可以覆盖这些点,在不覆盖(0,0)的情况下要添加多少根直线. 思路 在两个方向上添加直线,所以 ...

  9. 2022“杭电杯”中国大学生算法设计超级联赛(8)补题 1011 (持续更新中)

    目录 1011 Stormwind(贪心--分割矩形) 1011 Stormwind(贪心–分割矩形) /*题解:想要切割的次数最多,让原矩形的一边尽可能被多次切割,另一边紧跟即可*/ #includ ...

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

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

最新文章

  1. 基于python的图形化邮件发送程序(支持添加附件)
  2. 互联网金融2.0 这是最好的时代
  3. 服务器端的根目录放置文件,放置在网站根目录下
  4. app信息:PackageInfo+ApplicationInfo+ActivityInfo/ServiceInfo/ProviderInfo+PermissionInfo+...
  5. Java中常见的排序算法代码演示
  6. 用了这么久,你真的真的明白 HttpClient 的实现原理了吗?
  7. mac合上盖子不锁屏_macbook合上盖子不断网的设置
  8. python可以给你干什么-Python可以用来做什么 为你揭开python神秘面纱
  9. java基础题100道
  10. htmlunit第一个爬虫演示 目标网址http://ent.sina.com.cn/film/
  11. hget和get redis_Redis Hash 的 HSET、HGET、HMSET、HMGET 性能测试
  12. 【每日随笔】2021 年终总结 ( 学习和博客 | 技术学习方向 | 专业学习方向 | 写博客的技巧总结 | 工作成果 | 2022 年展望及职业规划 | 对 CSDN 的建议和期望 )
  13. 什么是二级域名,什么是二级目录?
  14. mac mini 蓝牙_Mac Mini
  15. CDMA HERT平台分布式基站 DBS3900 CDMA
  16. linux minicom centos,Centos6.5 minicom安装与配置
  17. win10更新后任务栏卡死解决方法
  18. 共筑未来 | 思腾合力加入光合组织,完成国产信创兼容适配
  19. Win10系统C++调用OpenCV实现网络摄像头录像和抓拍图片
  20. 泛泰binx和ota升级包下载工具Android版[2013.6.7提供源代码]

热门文章

  1. c语言单链表的按序号查找,以下为单链表按序号查找的运算,分析算法,请在______处填上正确的语句。 pointer find_lklist(1kl...
  2. 三大范式,ER图,外键,视图,索引,触发器
  3. border-radius的使用
  4. MySQL常用类型转换函数总结
  5. AHOI2019N省联考凉凉记
  6. three.js使用obj + mtl文件加载材质问题
  7. 基于Linux中的通讯录管理系统(C语言+双向循环链表+MySQL)
  8. 上海交大PMP——职场妈妈的学习干货分享
  9. [scRNA-seq]单细胞转录因子分析——SCENIC算法简析
  10. java将html转pdf