3B(小小贪心)

题目链接

题目大意:

有一辆载重量为 v 的货车, 准备运送两种物品。 物品 A 的重量为 1, 物体 B 的重量为 2, 每个物品都有一个价值。 求货车可以运送的物品的最大价值。

输入格式

第一个行包含两个整数 n 和 v,分别表示有 n 个物品, 货车的载重量为 v。 (1 ≤ n ≤ 10^5; 1 ≤ v ≤ 10^9)

接下来 n 行, 每行两个整数, 分别表示物品的重量 ti 和价值 pi。 , (1 ≤ ti ≤ 2; 1 ≤ pi ≤ 10000)

输出格式

第一行, 一个整数, 表示最大价值。

第二行 构成最大价值的物品的编号(如果答案不唯一 请输出其中任何一个)

思路:

大眼一看是背包问题,仔细一看V的数据范围是10^9算了吧,一定不是动态规划的背包了。那回是什么啊?题目中有说是最大价值,似乎和贪心有关系。确实,这题目用贪心的做法是可以A的。那怎么贪呢?

题目描述中有明确说明,物品的体积只可能是1或者2,那么我们是不是可以讨论呢?如果货车的容积为奇数的话,要保证其货品的价值最大化我们需要装至少一个体积为1的物品。那么剩下的体积为一的物品我们就可以将其转化为体积为二的物品(当然,我们为保证价值最大化需要将最大价值的体积为一的单独拿出来),先将体积为1物品根据价值由大到小进行排序,再将其转化为体积为2的物品,最后对处理后的物品排序即可。只是中间需要一些细节。比如如果最大价值为0的话,那他一定没有装任何物品,直接返回即可。还要注意数据范围,不要爆int了,这里直接开的long long .

AC代码如下:

#include<bits/stdc++.h>
#define L(i, j, k) for(int i = (j); i <= (k); ++i)
#define R(i, j, k) for(int i = (j); i <= (k); --i)
#define int long long
#define sz(a) ((int) (a).size())
#define vi vector< int >
#define me(a, x) memset(a, x, sizeof(a))
#define ull unsigned long long

using namespace std;
const int N = 1e5 + 7;

struct hh
{
	int w;
	int a, b;
	int v;
	int cnt;
} a[N], b[N]; 
int n, v;
int cnt_a, cnt_b;

bool cmp(struct hh a, struct hh b)
{
	return a.w > b.w;
}

void Main()
{
	cin >> n >> v;
	for(int i = 1; i <= n; i++ )
	{
		int op, w;
		cin >> op >> w;
		if(op == 2) 
		{
			a[cnt_a].cnt = 1, a[cnt_a].a = i, a[cnt_a].w = w, a[cnt_a++].v = op;
			
		}
		else 
		{
			b[cnt_b].cnt = 1, b[cnt_b].w = w, b[cnt_b].a = i,  b[cnt_b++].v = op;
		} 
	}
	sort(b, b + cnt_b, cmp);
		
	if(v & 1) 
	{
		a[cnt_a].w = b[0].w, a[cnt_a].cnt = 1, a[cnt_a].v = 1, a[cnt_a++].a = b[0].a;
		for(int i = 1; i + 1 < cnt_b; i += 2 )
		{
			int x = b[i].w + b[i + 1].w;
			a[cnt_a].w = x, a[cnt_a].a = b[i].a, a[cnt_a].b = b[i + 1].a, a[cnt_a].cnt = 2, a[cnt_a++].v = 2;  
		}
		if(!(cnt_b & 1)) a[cnt_a].w = b[cnt_b - 1].w, a[cnt_a].cnt = 1, a[cnt_a].a = b[cnt_b - 1].a, a[cnt_a++].v = 1;
	}
	else 
	{
		for(int i = 0; i + 1 < cnt_b; i += 2 )
		{
			int x = b[i].w + b[i + 1].w;
			a[cnt_a].w = x, a[cnt_a].a = b[i].a, a[cnt_a].b = b[i + 1].a, a[cnt_a].v = 2, a[cnt_a++].cnt = 2;
		}
		if(cnt_b & 1) a[cnt_a].w = b[cnt_b - 1].w, a[cnt_a].cnt = 1, a[cnt_a].a = b[cnt_b - 1].a, a[cnt_a++].v = 1;
	}
	
	sort(a, a + cnt_a, cmp);
	
	int V = v;
	int res = 0;
	for(int i = 0; i < cnt_a; i ++ )
	{
		
		int vv;
		vv = a[i].v;
		if(vv > V) continue;
		V -= vv;
		res += a[i].w;
		if(!V) break;
	}
	
	cout << res << '\n';
	if (!res) return ;//0就没有结果呗 
	
	V = v;
	for(int i = 0; i < cnt_a; i ++ )
	{
		int vv;
		vv = a[i].v;
		if(vv > V) continue;
		V -= vv;
		if(a[i].cnt == 1)
		{
			cout << a[i].a << ' ';
		}
		else 
		{
			cout << a[i].a << ' ' << a[i].b << ' ';
		}
		if(!V) break;
	}
	

}


signed main(){
	ios :: sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	Main();
	return 0;
}

/* stuff you should look for 你应该寻找的东西
 * int overflow, array bounds (int)溢出,数组边界
 * special cases (n=1?) 特殊情况(n=1?)
 * do smth instead of nothing and stay organized 做一些事情而不是什么也不做,保证效率
 * WRITE STUFF DOWN 将东西写下
 * DON'T GET STUCK ON ONE APPROACH 不要在一个地方死磕
 */

 

posted @ 2022-11-17 16:26  Luli&  阅读(66)  评论(0编辑  收藏  举报