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 不要在一个地方死磕
*/
没有什么能阻止我对知识的追求!!!