2022“杭电杯”中国大学生算法设计超级联赛(1)C.Backpack
题目链接: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相关推荐
- 2022“杭电杯”中国大学生算法设计超级联赛(8)
2022"杭电杯"中国大学生算法设计超级联赛(8) [题目链接](Search Result (hdu.edu.cn)) D Quel'Thalas 题目大意 在二维平面上,[0, ...
- 2022“杭电杯”中国大学生算法设计超级联赛(4)
2022"杭电杯"中国大学生算法设计超级联赛(4) [题目链接](Search Result (hdu.edu.cn)) D Link with Equilateral Trian ...
- 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 ...
- 2022“杭电杯”中国大学生算法设计超级联赛 (2) 杭电多校第二场
题目 1001 Static Query on Tree AC代码 1002 C++ to Python AC代码 1003 Copy AC代码 1005 Slayers Come AC代码 1007 ...
- 2022“杭电杯”中国大学生算法设计超级联赛(8)题解报告
Problem D. Quel'Thalas 题解: 手玩一下就会发现答案是就是2n. 代码: #include<iostream> #include<algorithm> # ...
- 2022“杭电杯”中国大学生算法设计超级联赛(6)题解报告
1006.Maex 题意: 给定一棵由从 1 到 n 编号的 n 个顶点组成的有根树,根为顶点 1.顶点 i 有一个自然数权重 ai,并且没有两个不同的顶点具有相同的权重.bu是以u为根的子树的权重的 ...
- 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)不变 ...
- 2022“杭电杯”中国大学生算法设计超级联赛(8)补题
1004 Quel'Thalas 题意 在二维平面上,点在坐标在[0,n]的区间内,通过添加无限长的直线可以覆盖这些点,在不覆盖(0,0)的情况下要添加多少根直线. 思路 在两个方向上添加直线,所以 ...
- 2022“杭电杯”中国大学生算法设计超级联赛(8)补题 1011 (持续更新中)
目录 1011 Stormwind(贪心--分割矩形) 1011 Stormwind(贪心–分割矩形) /*题解:想要切割的次数最多,让原矩形的一边尽可能被多次切割,另一边紧跟即可*/ #includ ...
- 2022“杭电杯”中国大学生算法设计超级联赛(1)1003 Backpack个人题解
Backpack 题目描述 有n件物品,他们各自都有体积vi和价值wi,给你一个体积为m的背包,求是否能从这n件物品中取出若干件,使得它们的体积之和恰好为m,所有物品的异或和最大,最大值是多少 分析 ...
最新文章
- 基于python的图形化邮件发送程序(支持添加附件)
- 互联网金融2.0 这是最好的时代
- 服务器端的根目录放置文件,放置在网站根目录下
- app信息:PackageInfo+ApplicationInfo+ActivityInfo/ServiceInfo/ProviderInfo+PermissionInfo+...
- Java中常见的排序算法代码演示
- 用了这么久,你真的真的明白 HttpClient 的实现原理了吗?
- mac合上盖子不锁屏_macbook合上盖子不断网的设置
- python可以给你干什么-Python可以用来做什么 为你揭开python神秘面纱
- java基础题100道
- htmlunit第一个爬虫演示 目标网址http://ent.sina.com.cn/film/
- hget和get redis_Redis Hash 的 HSET、HGET、HMSET、HMGET 性能测试
- 【每日随笔】2021 年终总结 ( 学习和博客 | 技术学习方向 | 专业学习方向 | 写博客的技巧总结 | 工作成果 | 2022 年展望及职业规划 | 对 CSDN 的建议和期望 )
- 什么是二级域名,什么是二级目录?
- mac mini 蓝牙_Mac Mini
- CDMA HERT平台分布式基站 DBS3900 CDMA
- linux minicom centos,Centos6.5 minicom安装与配置
- win10更新后任务栏卡死解决方法
- 共筑未来 | 思腾合力加入光合组织,完成国产信创兼容适配
- Win10系统C++调用OpenCV实现网络摄像头录像和抓拍图片
- 泛泰binx和ota升级包下载工具Android版[2013.6.7提供源代码]
热门文章
- c语言单链表的按序号查找,以下为单链表按序号查找的运算,分析算法,请在______处填上正确的语句。 pointer find_lklist(1kl...
- 三大范式,ER图,外键,视图,索引,触发器
- border-radius的使用
- MySQL常用类型转换函数总结
- AHOI2019N省联考凉凉记
- three.js使用obj + mtl文件加载材质问题
- 基于Linux中的通讯录管理系统(C语言+双向循环链表+MySQL)
- 上海交大PMP——职场妈妈的学习干货分享
- [scRNA-seq]单细胞转录因子分析——SCENIC算法简析
- java将html转pdf