题解:逃亡的准备 以及 有限背包的二进制优化

题目

【问题描述】

  在《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<bits/stdc++.h>

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<bits/stdc++.h>

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;
}

posted @ 2021-05-29 17:40  24Kmagic  阅读(254)  评论(0)    收藏  举报