宝物筛选

Posted 1129-tangqiyuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了宝物筛选相关的知识,希望对你有一定的参考价值。

传送门:https://www.luogu.org/problem/P1776

(多重背包)

很久就想用二进制拆分做一下了,这道题本来是用单调队列优化可惜蒟蒻我不会。

于是我就用二进制拆分牺牲空间复杂度换来了时间复杂度。

任何一个数都可以拆成二进制(其实不鬼畜)

e.g. 15=1+2+4+8    7=1+2+4 而拆出的这些数可以组成比这个数小的任意值。

所以代码如下

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<stack>
 5 #include<cstring>
 6 #include<cmath>
 7 using namespace std;
 8 int n,w;
 9 struct thing{
10     int v,w; 
11 }lis[1000005];
12 int tot;
13 int f[1000005];
14 inline int kd()
15 {
16     int x=0,f=1;char ch=getchar();
17     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
18     while(ch>=0&&ch<=9){x=x*10+(ch^48);ch=getchar();}
19     return x*f;
20 }
21 int main()
22 {
23     n=kd(),w=kd();
24     for(register int i=1;i<=n;i++)
25     {
26         int x=1;
27         int a=kd(),b=kd(),c=kd();
28         while(c-x>=0)//二进制拆分本尊 
29         {
30             c-=x;
31             lis[++tot].w=x*a;
32             lis[tot].v=x*b;
33             x<<=1;
34         }
35         if(c!=0)//判断是否还有剩下的 
36         {
37             lis[++tot].w=c*a;
38             lis[tot].v=c*b;
39         }
40     }
41     for(register int i=1;i<=tot;i++)//普通的01背包乖乖 
42     {
43         for(register int j=w;j>=lis[i].v;j--)
44         {
45             f[j]=max(f[j],f[j-lis[i].v]+lis[i].w);
46         }
47     }
48     cout<<f[w];
49 }

 

  

以上是关于宝物筛选的主要内容,如果未能解决你的问题,请参考以下文章

宝物筛选

洛谷P1776 宝物筛选_NOI导刊2010提高(02)

P1776 宝物筛选_NOI导刊2010提高(02)(背包的二进制优化)

ybtoj背包问题课堂过关DP例题3宝物筛选

题解luogu P1776 宝物筛选

[洛谷P1776]宝物筛选