【学习笔记】CF3B Lorry 题解

题目传送门

正解

思路

  • 因为物品的重量只有 1 和 2,所以考虑暴力枚举选择多少个 2 ,剩下的尽可能多地填充 1 即可。

  • 为什么“尽可能多”正确呢?很显然,这是因为物品的价值 \(\ge 1\) 。

  • 至于怎么选择,只需要将物品的价值从大到小排序,然后取靠前的即可。

  • 注意使用前缀和优化。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
ll n,v;
struct num{
	ll nu,po;
}j[100233],o[100233];
ll cj,co,qj,qo,t,w,ans=-1919810,rere=-1919810;
inline bool cmp(num a,num b){
	return ((a.nu>b.nu)?true:((a.nu==b.nu)?a.po<=b.po:false));
}
int main(){
	scanf("%lld%lld",&n,&v);
	for(int i=1;i<=n;++i){
		scanf("%lld%lld",&t,&w);
		if(t==1){j[++cj].nu=w;j[cj].po=i;}
		else{o[++co].nu=w;o[co].po=i;}
	}
	sort(j+1,j+cj+1,cmp);
	sort(o+1,o+co+1,cmp);
	ll fff=max(cj,co);
	for(int i=1;i<=fff;++i){
		j[i].nu+=j[i-1].nu;
		o[i].nu+=o[i-1].nu;
	}
	for(int i=0;i<=co;++i){
		if((i<<1)>v) break;
		ll ott=min(v-(i<<1),cj);
		rere=o[i].nu+j[ott].nu;
		if(rere>ans){ans=rere;qj=ott;qo=i;}
	}
	printf("%lld\n",ans);
	for(int i=1;i<=qj;++i)
		printf("%lld ",j[i].po);
	for(int i=1;i<=qo;++i)
		printf("%lld ",o[i].po);
	return 0;
}
/*
8 1919810
1 133
1 23333
1 33333
1 4333
1 5333
1 6333
1 222
1 998244353
*/
上一篇:拉格朗日函数


下一篇:拉格朗日对偶问题 Lagrange duality