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 不要在一个地方死磕 */
没有什么能阻止我对知识的追求!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?