【CodeForces】CF3B Lorry

题目地址:

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 1n105;1v109
接下来 n n n行, 每行两个整数, 分别表示物品的重量 ti 和价值 pi。 , ( 1 ≤ t i ≤ 2 ; 1 ≤ p i ≤ 10000 1 ≤ t_i ≤ 2; 1 ≤ p_i ≤ 10000 1ti2;1pi10000)

输出格式:
第一行,一个整数,表示最大价值。
第二行,构成最大价值的物品的编号(如果答案不唯一 请输出其中任何一个)

题目描述:
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} 1n105 ; 1 ≤ v ≤ 1 0 9 1\le v\le 10^{9} 1v109 ), 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 1ti2 ; 1 ≤ p i ≤ 1 0 4 1\le p_{i}\le 10^{4} 1pi104 ), 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{(vk)/2,c2}个,这种方案的物品 1 1 1总价值可以开个变量每次循环加一下,物品 2 2 2总价值直接查询前缀和,那么总的总价值即为两个总价值相加。代码如下:

#include <iostream>
#include <algorithm>
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)

### 关于 Codeforces 1853B 的题解与实现 尽管当前未提供关于 Codeforces 1853B 的具体引用内容,但可以根据常见的竞赛编程问题模式以及相关算法知识来推测可能的解决方案。 #### 题目概述 通常情况下,Codeforces B 类题目涉及基础数据结构或简单算法的应用。假设该题目要求处理某种数组操作或者字符串匹配,则可以采用如下方法解决: #### 解决方案分析 如果题目涉及到数组查询或修改操作,一种常见的方式是利用前缀和技巧优化时间复杂度[^3]。例如,对于区间求和问题,可以通过预计算前缀和数组快速得到任意区间的总和。 以下是基于上述假设的一个 Python 实现示例: ```python def solve_1853B(): import sys input = sys.stdin.read data = input().split() n, q = map(int, data[0].split()) # 数组长度和询问次数 array = list(map(int, data[1].split())) # 初始数组 prefix_sum = [0] * (n + 1) for i in range(1, n + 1): prefix_sum[i] = prefix_sum[i - 1] + array[i - 1] results = [] for _ in range(q): l, r = map(int, data[2:].pop(0).split()) current_sum = prefix_sum[r] - prefix_sum[l - 1] results.append(current_sum % (10**9 + 7)) return results print(*solve_1853B(), sep=&#39;\n&#39;) ``` 此代码片段展示了如何通过构建 `prefix_sum` 来高效响应多次区间求和请求,并对结果取模 \(10^9+7\) 输出[^4]。 #### 进一步扩展思考 当面对更复杂的约束条件时,动态规划或其他高级技术可能会被引入到解答之中。然而,在没有确切了解本题细节之前,以上仅作为通用策略分享给用户参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值