这道题洛谷上的翻译是错的,最后输出格式那里应该是输出一行所选物品的编号,中间用空格隔开
手动模拟01背包
这道题看上去很像是01背包的模板题,但是很明显,v=1e9,正常的01背包是肯定会爆掉62MB的内存的,所以不可能用普通的01背包来做,
但是转念一想,这道题是由10背包魔改过来的,增加的难度是空间的问题。那么如果可以解决掉空间上的不足,用01背包的思路来做即可
先把物品1或2 分成两组,按价值排序。
模拟01背包,先用前缀和处理第二组(质量为2),然后模拟for循环从0开始,每次取第一组的一个,比较是全拿2最大还是拿当前的这个1总质量最大,最后输出即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5+7;
const ll mod=2147483647;
ll n,v,ans,sum;
struct node
{
ll val,id;
bool operator<(const node & t)const
{
return val>t.val;
}
}t1[N<<1],t2[N<<1];
ll cnt1,cnt2;
ll pre[N],ans1,ans2;
int main()
{
scanf("%lld %lld",&n,&v);
for(int i=1;i<=n;++i)
{
ll a,b;
scanf("%lld %lld",&a,&b);
if(a==1)t1[++cnt1].val=b,t1[cnt1].id=i;
if(a==2)t2[++cnt2].val=b,t2[cnt2].id=i;
}
sort(t1+1,t1+1+cnt1),sort(t2+1,t2+1+cnt2);
for(int i=1;i<=cnt2;++i)
pre[i]=pre[i-1]+t2[i].val;
for(int i=0;i<=min(cnt1,v);++i)
{
sum+=t1[i].val;
if(sum+pre[min(cnt2,(v-i)/2)]>ans)
{
ans=sum+pre[min(cnt2,(v-i)/2)];
ans1=i,ans2=min(cnt2,(v-i)/2);
}
}
printf("%lld\n",ans);
for(int i=1;i<=ans1;++i)
printf("%lld%s",t1[i].id," ");
for(int i=1;i<=ans2;++i)
printf("%lld%s",t2[i].id,i==ans2?"\n":" ");
}
有任何疑问欢迎评论哦虽然我真的很菜
<stron>
</stron>