题解 CF3B 【Lorry】
这道题大可看成贪心来做。
根据题目所说,物品重量无非两种,要么重量是 1 ,要么重量是 2 ,那么按物品重量把它们分成两类,用一个 \(pair<int,int>\) 来存物品的价值和序号(因为输出要用),按价值对两个物品序列降序排序。
然后枚举用 \(i\) 个重量为 1 的物品(理论上 2 也可以),那么就用了 \(\frac{v-i}{2}\) 个重量为 2 的物品,贪心计算当前的价值总和(按照排序尽量取价值大的),取 \(\max\) 同时记录方案。
很显然这样直接求会 TLE ,那么我们要做的就是祭出优化!
优化: 同样显然,预处理出质量为 2 物体价值的前缀和,枚举循环内部时直接用就完了。
代码:
#include<bits/stdc++.h>
#define pi pair<int,int>
#define F first
#define S second
#define re register
using namespace std;
pi a[100005],b[100005];
int t1,t2,num[100005];
int ans,sum,maxi,maxj;
bool cmp(pi a,pi b) {//sort比较函数(降序)
return a.F>b.F;
}
inline int read() {//快读
int sum=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
sum=(sum<<3)+(sum<<1)+ch-'0';
ch=getchar();
}
return sum*w;
}
int main() {
int n,v;
n=read();
v=read();
for(re int i=1;i<=n;i++) {
int opt=read(),x=read();
if(--opt) b[++t2]=make_pair(x,i);
else a[++t1]=make_pair(x,i);
}
sort(a+1,a+t1+1,cmp);
sort(b+1,b+t2+1,cmp);//STL大法好
for(int i=1;i<=t2;i++) {
num[i]=num[i-1]+b[i].F;//预处理前缀和
}
for(re int i=0;i<=t1&&i<=v;i++) {//i个质量1物品
int j=min((v-i)>>1,t2);//j个质量2物品
sum+=a[i].F;
if(sum+num[j]>ans) {
ans=sum+num[j];
maxi=i;
maxj=j;
}
}
cout<<ans<<endl;
for(re int i=1;i<=maxi;i++)
cout<<a[i].S<<' ';
for(re int i=1;i<=maxj;i++)
cout<<b[i].S<<' ';
return 0;
}
任何一个伟大的计划,都有一个微不足道的开始