宝物筛选_NOI导刊2010提高(02)(二进制拆分/优先队列优化多重背包)
题目描述
终于,破解了千年的难题。小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF可发财了,嘎嘎。但是这里的宝物实在是太多了,小FF的采集车似乎装不下那么多宝物。看来小FF只能含泪舍弃其中的一部分宝物了……小FF对洞穴里的宝物进行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始了宝物筛选工作:小FF有一个最大载重为W的采集车,洞穴里总共有n种宝物,每种宝物的价值为v[i],重量为w[i],每种宝物有m[i]件。小FF希望在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。
输入格式
第一行为一个整数N和w,分别表示宝物种数和采集车的最大载重。
接下来n行每行三个整数,其中第i行第一个数表示第i类品价值,第二个整数表示一件该类物品的重量,第三个整数为该类物品数量。
输出格式
输出仅一个整数ans,表示在采集车不超载的情况下收集的宝物的最大价值。
输入输出样例
输入 #14 20 3 9 3 5 9 1 9 4 2 8 1 3输出 #147说明/提示
对于30%的数据:n≤∑m[i]≤10^4;0≤W≤10^3。
对于100%的数据:n≤∑m[i]≤10^5;
0 <w≤4*10^4:1≤n<100。
多重背包在不优化的情况下复杂度为:m(背包体积)$\sum_{i=1}^{n}wcnt$
二进制优化复杂度:m(背包体积)log($\sum_{i=1}^{n}wcnt$)
附上二进制优化代码
1 #include<bits/stdc++.h> 2 #define re register int 3 #define maxn 40000+5 4 #define maxn1 1600+5 5 6 7 using namespace std; 8 int f[maxn],n,m; 9 int wei[maxn1],val[maxn1]; 10 int weight,value,wcnt,cnt; 11 int main() 12 { 13 ios::sync_with_stdio(false); 14 cin>>n>>m; 15 for(re i=1;i<=n;i++) 16 { 17 cin>>value>>weight>>wcnt; 18 for(re tmp=1;tmp<=wcnt;tmp<<=1) 19 { 20 val[++cnt]=value*tmp; 21 wei[cnt]=weight*tmp; 22 wcnt-=tmp; 23 } 24 if(wcnt) val[++cnt]=value*wcnt,wei[cnt]=weight*wcnt; 25 } 26 for(re i=1;i<=cnt;i++) 27 for(re j=m;j>=wei[i];j--) 28 f[j]=max(f[j],f[j-wei[i]]+val[i]); 29 cout<<f[m]; 30 return 0; 31 }
单调队列优化复杂度:m*$\sum_{i=1}^{n}wcnt$
具体理解可以参见https://blog.csdn.net/flyinghearts/article/details/5898183
1 #include<bits/stdc++.h> 2 #define re register int 3 #define maxn 40000+5 4 5 using namespace std; 6 int n,m; 7 int f[maxn],cnt[maxn],q[maxn]; 8 int ans; 9 int sum,maxcnt; 10 int weight,value,wcnt,tmp,tmp1; 11 int main() 12 { 13 ios::sync_with_stdio(false); 14 cin>>n>>m; 15 for(re i=1;i<=n;i++) 16 { 17 cin>>value>>weight>>wcnt; 18 if(weight==0) { 19 tmp+=value*wcnt; 20 continue; 21 } 22 sum=min(wcnt,m/weight); 23 for(re j=0;j<weight;j++) 24 { 25 maxcnt=(m-j)/weight; 26 int head=1,tail=0; 27 for(re k=0;k<=maxcnt;k++) 28 { 29 int tmp1=f[j+k*weight]-k*value; 30 while(head<=tail&&q[tail]<=tmp1) 31 tail--; 32 q[++tail]=tmp1; 33 cnt[tail]=k; 34 while(head<=tail&&cnt[head]+sum<k) head++; 35 f[j+k*weight]=max(f[j+k*weight],q[head]+k*value); 36 ans=max(ans,f[j+k*weight]); 37 } 38 } 39 } 40 cout<<tmp+ans; 41 return 0; 42 }
We're the lovers above the city.