Dividing(HDU 1059)(多重背包_二进制优化)
题目链接:
题意:有价值分别为1,2,3,4,5,6的marbles(大理石)若干,问是否能使这些marbles平分。【marbles总数不超过2e4(很明显这是一个大常数,所以用二进制优化来做)】
My_idea(关于二进制优化)
首先的话我们先看14=1+2+4+7({1,2,4,7}可以组成1到14之间的所有的数,不多也不少,这个很重要必须要不多也不少!如果是{1,2,4,8}那么还会有15,这就不可以!)
所以利用这一点我们可以将num[i]按照二进制划分为1,2,4,……这些数,也就是将num[i]个价值为i的物品划分为了1,2,4,……个价值为i * 1 , i * 2, i * 4……的新物品,这样的话我们就可以将后者看成一个数量小的01背包再来处理。(不这样优化的话我们就是一个大常数的多重背包,会T)
其次的话,物品只有价值和数量这两个属性,对于一种物品我们二进制转换之后就只有(新)价值这一个属性,而且我们要的答案是能否将所有的marbles价值平分,所以我们的dp[i]就可以用来看价值为i的状态是不是存在,最后只需要看dp[C]是否存在即可。要注意的就是1、dp[j-val]要存在,dp[j]才能存在;2、dp[0]是背包中无价值的状态,初始化要为1。
My_feeling:
首先就题意来说读了n久没读懂,就是这句话:
The lines consist of six non-negative integers n1, n2, …, n6, where ni is the number of marbles of value i. So, the example from above would be described by the input-line ``1 0 1 2 0 0’’. The maximum total number of marbles will be 20000.
不知道为什么我开始的时候就是觉得是20000是前边说的那个样例的价值,我就说到底是怎么得来的?也太迷了吧??一脸懵……QAQ
后来不行了实在是不懂题意,就看他们的博客,写的题意也就是题目字面意思,输入的六个数是大理石的数量,可是20000到底什么什么鬼???于是又开始一个词一个词读,我的天呐,从前天晚上就读了的题到今天上午终于读懂了,原来是数量和的最大值?!这真的说明了我是个白痴……QAQ
读懂题意之后,开始想题,知道这个该用二进制优化,但是不知道怎么处理,于是就想问问谁,但是又找不到人问(好卑微,没啥熟人),博客吧由于种种原因看不下去,就昨天晚上到现在就一直打开这道题的界面然后心烦、心烦、心烦……就打开QQ音乐听歌……先要positive起来……QAQ
下午要打排位了,不知道吧,因为什么,就强迫自己看博客,完完整整看了一遍代码,然后终于理解了之后就开始自己敲。敲了样例过了,感觉没问题,交!WA!于是发现没有初始化dp[0],理解不够深刻吧,再交还是又WA!然后又看了眼题,发现要每个cases中间有blank line隔开,于是又调整了以下,再交!还是WA!又开始debug,发现num[i]没有判零,改了交,WA!然后又发现后边val没有判零,交了!WA!然后就各种怀疑自己的代码,改了些稀奇古怪的地方还是WA了几次,中间还CE了一次。然后就开始试边界20000,发现直接就运行结束了报错,然后就调试了0 0 0 0 0 2000样例,发现中间 j=num[i]; 这一句敲飘了,写成了num[j]直接就超数组大小了。改完交了终于AC了!QAQ……提起AC又想起跳waacking的AC,interesting!
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <list>
#include <map>
#define P(x) x>0?x:0
#define INF 0x3f3f3f3fusing namespace std;
typedef long long ll;
typedef vector<int>:: iterator VITer;
const int maxN=12e4;int dp[maxN],C;
int num[10];
int val,sum;void init()
{sum=0;memset(dp,0, sizeof(dp));dp[0]=1;//背包内价值为0这个状态是可以存在的
}int main()
{int Case=0;while(true){if(Case)printf("\n");init();for(int i=1;i<=6;i++){scanf("%d",&num[i]);sum+=num[i]*i;}if(!sum)//输入为0 0 0 0 0 0break;if(sum&1)//sum为奇数,一定不能平分{printf("Collection #%d:\nCan't be divided.\n",++Case);continue;}C=sum/2;for(int i=1;i<=6;i++){if(!num[i])//如果是0的话就不能再跑了continue;int j;for(j=1;j<=num[i];j<<=1)//将num[i]个i价值的物品转换为一个01背包,假如说是14=1+2+4+7,{1,2,4,7}可以组成1到14所有的数值,所以将价值重新定义后,就是一个01背包{//(二进制优化->可以将多重背包物品数量的大常数转换为小常数)val=i*j;for(int k=C;k>=val;k--){if(dp[k-val]&&(!dp[k]))//k状态没走过,k-val状态走过,那么此刻加上val就是可走的dp[k]=1;//即dp[(k-val)+val]可以有}num[i]-=j;}j=num[i];//此时的num[j]->2的次幂之外的数val=i*j;if(val)//如果是0就不能跑{for(int k=C;k>=val;k--){if(dp[k-val]&&(!dp[k]))dp[k]=1;//即dp[(k-val)+val]可以有}}}if(dp[C])printf("Collection #%d:\nCan be divided.\n",++Case);elseprintf("Collection #%d:\nCan't be divided.\n",++Case);}return 0;
}
因为一个空格行的输出! PE了5次又!
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <list>
#include <map>
#define INF 0x3f3f3f3f
#define MID l + r >> 1
#define lsn rt << 1
#define rsn rt << 1 | 1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qrusing namespace std;
typedef long long ll;
typedef vector<int>:: iterator VITer;
const int maxN = 12e4 + 5;
const int maxE = 1e4 +5;int a[10];
int dp[maxN];int main()
{int Case = 0;while(~scanf("%d", &a[1])){int sum = a[1];for(int i = 2; i <= 6 ; i ++ ){scanf("%d", &a[i]);sum += a[i] * i;}if(sum == 0)break;if(sum & 1){printf("Collection #%d:\nCan't be divided.\n\n", ++ Case );continue;}int C = sum >> 1;memset(dp, 0, sizeof(dp)); dp[0] = 1;// 目的:找所有apart大理石可的价值for(int val = 1; val <= 6 ; val ++ ) // 价值{for(int num = 1 ; num <= a[val] ; num <<= 1){int new_ = num * val; // 新价值for(int j = C ; j >= new_ ; j --)if(!dp[j] && dp[j - new_])dp[j] = 1;a[val] -= num;}if(a[val]){int new_ = a[val] * val;for(int j = C ; j >= new_ ; j -- )if(!dp[j] && dp[j - new_])dp[j] = 1;}}if(dp[C])printf("Collection #%d:\nCan be divided.\n\n", ++ Case);elseprintf("Collection #%d:\nCan't be divided.\n\n", ++ Case);}return 0;
}
Dividing(HDU 1059)(多重背包_二进制优化)相关推荐
- 为了OFFER,菜鸟的我必须搞懂动态规划系列三个背包问题之多重背包(二进制优化方法)
@Author:Runsen @Date:2020/9/17 多重背包有三层循环,如果数据非常的大,那么程序就会变得非常悲伤.在多重背包的问题,其实更多的是考查多重背包的二进制优化方法.学习二进制优化 ...
- 多重背包(二进制优化)
问题概述:有一个容量为V的背包和n个物品,第i种物品最多有n[i]件可用,每件体积是w[i],求解将哪些物品装入背 包可使这些物品的价值尽可能接近V但不大于V(POJ1276) 输入样例: ...
- 多重背包的二进制优化(ybtoj-宝物筛选)
文章目录 题目描述 解析 朴素算法 代码 二进制优化 代码 thanks for reading! 题目描述 解析 朴素算法 首先考虑朴素算法 把数量为num的物体拆成num个子物体 其价值与重量是原 ...
- HDU 2844 (多重背包)
多重背包(二进制优化)模板 题意: 有n个硬币,每一个硬币有自己的数值Vi,其个数为Ci.不同硬币的不同组合能买到不同物品,问在1~V的区间内最多能买到多少不同种类的物品. 思路: 其实题意也就是求硬 ...
- 多重背包单调队列优化思路_动态规划入门——多重背包与单调优化
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法与数据结构的第14篇文章,也是动态规划专题的第三篇. 在之前的文章当中,我们介绍了多重背包的二进制拆分的解法.在大多数情况下,这种 ...
- 动态规划入门——多重背包与单调优化
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法与数据结构的第14篇文章,也是动态规划专题的第三篇. 在之前的文章当中,我们介绍了多重背包的二进制拆分的解法.在大多数情况下,这种 ...
- 多重背包2[二进制位优化]
数据范围加强一下 0<N≤1000 0<V≤2000 0<vi,wi,si≤2000 这时候O(n3)O(n^3)O(n3)的算法不行,需要优化成O(N∗logs∗V)O(N*log ...
- ZCMU 1919: kirito's 星爆气流斩【01背包的二进制优化】
ZCMU 1919: kirito's 星爆气流斩 Time Limit: 2 Sec Memory Limit: 128 MB Description 主角kirito是使用世界首款完全潜行游戏& ...
- POJ1276 多重背包DP 生命不息优化不止
POJ1276 多重背包DP题 这道题弄了一个早上-一看题目是多重背包题直接敲了一个三重for循环,无限TLE,下面附上好几种解法. Description A Bank plans to insta ...
最新文章
- lvm自动扩容到固定分区脚本
- java中gson的简单使用
- 容量法和库仑法的异同点_【图文专辑】第十讲:容量法高锰酸盐指数的测定
- python list同步删除
- Work Measurement - 1
- 介绍一下mysql的存储过程和搜索引擎_MySQL基础(四)—存储过程和存储引擎
- 新垣结衣AI换脸郭德纲 网友:换脸史上最惨的车祸现场
- RuntimeWarning: numpy.dtype size changed, may indicate binary incompatibility.
- 李宏毅机器学习——结构化支持向量机
- 记录一次常见的错误:java.sql.SQLException: Got error 28 from storage engine
- MFC 盾webBrowser打开弹出的页面
- three.js 学习1
- 等价类划分法测试用例设计
- php paypal支付接口文档,php 实现PayPal支付
- Windows2012R2,2008R2 Internet时间无法同步成功解决方案
- SpringBoot(六)打包方式
- 从设计的角度看 Redux
- 桌面在计算机哪个文件,电脑桌面上的文件在C盘哪个文件里面
- virsh 保护命令 virtual protect rebase
- JeecgBoot 2.4.6 版本发布,基于代码生成器的企业级低代码平台