https://www.luogu.com.cn/problem/CF3B
题意翻译:
有一辆载重量为 v v v的货车, 准备运送两种物品。 物品A的重量为 1 1 1,物体B的重量为 2 2 2,每个物品都有一个价值。求货车可以运送的物品的最大价值。
输入格式:
第一个行包含两个整数 n n n和 v v v,分别表示有 n n n个物品, 货车的载重量为 v v v, 1 ≤ n ≤ 1 0 5 ; 1 ≤ v ≤ 1 0 9 1 ≤ n ≤ 10^5; 1 ≤ v ≤ 10^9 1≤n≤105;1≤v≤109
接下来 n n n行, 每行两个整数, 分别表示物品的重量 ti 和价值 pi。 , ( 1 ≤ t i ≤ 2 ; 1 ≤ p i ≤ 10000 1 ≤ t_i ≤ 2; 1 ≤ p_i ≤ 10000 1≤ti≤2;1≤pi≤10000)
输出格式:
第一行,一个整数,表示最大价值。
第二行,构成最大价值的物品的编号(如果答案不唯一 请输出其中任何一个)
题目描述:
A group of tourists is going to kayak and catamaran tour. A rented lorry has arrived to the boat depot to take kayaks and catamarans to the point of departure. It’s known that all kayaks are of the same size (and each of them occupies the space of 1 1 1 cubic metre), and all catamarans are of the same size, but two times bigger than kayaks (and occupy the space of 2 2 2 cubic metres).
Each waterborne vehicle has a particular carrying capacity, and it should be noted that waterborne vehicles that look the same can have different carrying capacities. Knowing the truck body volume and the list of waterborne vehicles in the boat depot (for each one its type and carrying capacity are known), find out such set of vehicles that can be taken in the lorry, and that has the maximum total carrying capacity. The truck body volume of the lorry can be used effectively, that is to say you can always put into the lorry a waterborne vehicle that occupies the space not exceeding the free space left in the truck body.
输入格式:
The first line contains a pair of integer numbers n n n and v v v ( 1 ≤ n ≤ 1 0 5 1\le n\le 10^{5} 1≤n≤105 ; 1 ≤ v ≤ 1 0 9 1\le v\le 10^{9} 1≤v≤109 ), where n n n is the number of waterborne vehicles in the boat depot, and v v v is the truck body volume of the lorry in cubic metres. The following n n n lines contain the information about the waterborne vehicles, that is a pair of numbers t i t_{i} ti , p i p_{i} pi ( 1 ≤ t i ≤ 2 1\le t_{i}\le 2 1≤ti≤2 ; 1 ≤ p i ≤ 1 0 4 1\le p_{i}\le 10^{4} 1≤pi≤104 ), where t i t_{i} ti is the vehicle type ( 1 1 1 – a kayak, 2 2 2 – a catamaran), and p i p_{i} pi is its carrying capacity. The waterborne vehicles are enumerated in order of their appearance in the input file.
输出格式:
In the first line print the maximum possible carrying capacity of the set. In the second line print a string consisting of the numbers of the vehicles that make the optimal set. If the answer is not unique, print any of them.
思路是贪心,首先容易想到相同重量的情况下,优先选择价值高的,所以我们先将物品按重量分为两类,然后各自按价值从大到小排序。设物品 k k k有 c k c_k ck个。接着枚举重量 1 1 1的物品选多少个(当然如果选 c c c个,肯定是选价值最大的那 c c c个),可以不选,此时全选物品 2 2 2,个数为 min { ⌊ v / 2 ⌋ , c 2 } \min\{\lfloor v/2\rfloor, c_2\} min{⌊v/2⌋,c2},那么总价值就是物品 2 2 2前这么多个物品总价值(可以对物品 2 2 2的价值求个前缀和 p p p),接着枚举物品 1 1 1选 1 , 2 , . . . , min { v , c 1 } 1,2,...,\min\{v,c_1\} 1,2,...,min{v,c1}个,那么当物品 1 1 1选 k k k个的时候,物品 2 2 2就选 min { ⌊ ( v − k ) / 2 ⌋ , c 2 } \min\{\lfloor (v-k)/2\rfloor, c_2\} min{⌊(v−k)/2⌋,c2}个,这种方案的物品 1 1 1总价值可以开个变量每次循环加一下,物品 2 2 2总价值直接查询前缀和,那么总的总价值即为两个总价值相加。代码如下:
#include
#include
using namespace std;
using PII = pair<int, int>;
const int N = 1e5 + 10;
int n, v;
// v1[i]为重量为1的物品中价值第i位的物品价值和下标
PII v1[N], v2[N];
int cnt1, cnt2;
int pre[N];
int res, max1, max2;
int main() {
scanf("%d%d", &n, &v);
for (int i = 1; i <= n; i++) {
int t, p;
scanf("%d%d", &t, &p);
if (t == 1) v1[++cnt1] = {p, i};
else v2[++cnt2] = {p, i};
}
// 对价值从大到小排序
sort(v1 + 1, v1 + 1 + cnt1, greater<>());
sort(v2 + 1, v2 + 1 + cnt2, greater<>());
for (int i = 1; i <= cnt2; i++)
pre[i] = v2[i].first + pre[i - 1];
// 枚举物品1选多少个
for (int i = 0, sum = 0; i <= min(cnt1, v); i++) {
// 求出当前方案的物品1的总价值
sum += v1[i].first;
// 计算一下物品2选多少个
int j = min(v - i >> 1, cnt2);
// 如果当前方案价值更高,则更新答案
if (sum + pre[j] > res) {
res = sum + pre[j];
max1 = i;
max2 = j;
}
}
printf("%d\n", res);
for (int i = 1; i <= max1; i++) printf("%d ", v1[i].second);
for (int i = 1; i <= max2; i++) printf("%d ", v2[i].second);
}
时间复杂度 O ( n 1 log n 1 + n 2 log n 2 ) O(n_1\log n_1+n_2\log n_2) O(n1logn1+n2logn2), n k n_k nk是重量 k k k的物品多少个,空间 O ( n 1 + n 2 ) O(n_1+n_2) O(n1+n2)。