题解:逃亡的准备 以及 有限背包的二进制优化
目录
- 题目
- 【问题描述】
- 【输入格式】
- 【输出格式】
- 【输入样例】
- 【输出样例】
- 解析
- 什么是二进制优化呢?
题目
【问题描述】
在《Harry Potter and the Deathly Hallows》中,Harry Potter他们一起逃亡,现在有许多的东西要放到赫敏的包里面,但是包的大小有限,所以我们只能够在里面放入非常重要的物品。现在给出该种物品的数量、体积、价值的数值,希望你能够算出怎样能使背包的价值最大的组合方式,并且输出这个数值,赫敏会非常感谢你。
【输入格式】
第1行有2个整孰物品种数n和背包装载体积v;
第2行到i+l行每行3个整数,为第i种物品的数量m、体积w、价值s。
【输出格式】
仅包含一个整数,即为能拿到的最大的物品价值总和。
【输入样例】
2 10
3 4 3
2 2 5
【输出样例】
13
解析
这道题是一个有限背包,我们可以按照有限背包的板子写:
#include
using namespace std;
int n,v;
struct bag {
int m,w,s;
} a[1000001];
int dp[1000001];
int main() {
scanf("%d %d" ,&n ,&v);
for(int i = 1; i <= n; i++) {
scanf("%d %d %d" ,&a[i].m,&a[i].w,&a[i].s);
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= a[i].m; j++) {
for(int k = v; k >= a[i].w; k--) {
dp[k] = max(dp[k],dp[k - a[i].w] + a[i].s);
}
}
}
printf("%d" ,dp[v]);
return 0;
}
但是这样做复杂度是有亿点点高的,高到可以卡掉三个点,所以我们需要用到二进制优化来帮我们降低复杂度:
什么是二进制优化呢?
顾名思义,我们把同种每2n的物品放在一起,当作一件物品(其价值和体积需要对应累加),处理完后当作0 1背包来做即可。
比如7个物品:
7 = 1 + 2 + 4.
而有意思的是,1,2,4正好可以凑出从1到7所有的整数,因此我们这么做在dp的时候是不会少情况的(具体证明我也不会)。
接下来就是二进制优化之后的代码:
#include
using namespace std;
int ans = 0,nn = 0,t;
int dp[2001]= { },j,w[100001],s[100001];
int a[100001],b[1000001];
int m[100001];
int n,v;
int cnt = 0;
int main() {
scanf("%d %d" ,&n,&v);
for(int i = 1;i <= n; i++){
scanf("%d %d %d" ,&m[i],&a[i],&b[i]);
}
for(int i = 1;i <= n; i++){
for(int j = 1;j <= m[i];j<<=1){
w[++cnt] = j * a[i];
s[cnt] = j * b[i];
m[i] = m[i] - j;
}
if(m[i] > 0){
s[++cnt] = m[i] * b[i];
w[cnt] = m[i] * a[i];
}
}
for(int i = 1; i <= cnt; i++) {
for(int k = v; k >= w[i]; k--) {
dp[k] = max(dp[k],dp[k - w[i]] + s[i]); //处理完后所有的都要换成新数组
}
}
printf("%d" ,dp[v]);
return 0;
}