You Like Cake(超大01背包模板题)
Posted smallocean
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了You Like Cake(超大01背包模板题)相关的知识,希望对你有一定的参考价值。
You Like Cake
题目描述
双十一就要来啦!而Yuno刚刚获得了一笔X元的奖金。那么是不是应该清空下购物车呢?
购物车总共有N个物品,每个物品的价格为Vi,Yuno想尽可能地把手头的奖金给花光,所以她要精心挑选一些商品,使得其价格总和最接近但又不会超过奖金的金额。那么Yuno最后最少可以剩下多少钱呢?
输入
第一行,两个正整数N和X。
第二行,N个正整数Vi表示第i个物品的价格。
输出
输出一个整数,表示Yuno最后最少可以剩下的钱数。
样例输入
4 50
1 2 3 4
样例输出
40
提示
对于100的数据,N≤40,X,Vi≤109
背包容量过大采用折半之后二进制枚举子集,再二分查找
upper_bound返回的是第一个大于查找的数的位置
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[25],b[25];
ll s[(1<<21)+1],f[(1<<21)+1];
int main(){
int n;
ll m;scanf("%d%lld",&n,&m);
for(int i=1;i<=n;++i){
if(i<=n/2){
scanf("%lld",&a[i]);
}
else scanf("%lld",&b[i-n/2]);
}
int k=n/2;
int pos=0;
for(int i=0;i<(1<<k);++i){
for(int j=1;j<=k;++j){
if(i&(1<<(j-1))){
s[pos]+=a[j];
}
}
pos++;
}
int len=(int)(unique(s,s+pos)-s);
sort(s,s+len);
pos=0;k=n-k;
for(int i=0;i<(1<<k);++i){
for(int j=1;j<=k;++j){
if(i&(1<<(j-1))){
f[pos]+=b[j];
}
}
pos++;
}
ll ans=0;
int op;
for(int i=0;i<pos;++i){
if(m<f[i]) continue;
op=upper_bound(s,s+len,m-f[i])-s;
op--;
if(op>=0){
ans=max(ans,s[op]+f[i]);
}
}
printf("%lld
",m-ans);
return 0;
}
以上是关于You Like Cake(超大01背包模板题)的主要内容,如果未能解决你的问题,请参考以下文章