题解 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;
}
原文地址:https://www.cnblogs.com/ahawzlc/p/12711953.html