Charlie_Parker 2023-10-02 12:51 采纳率: 40%
浏览 12

神奇的口袋 注意数据范围

蜗蜗有一个神奇的口袋,口袋可以装下体积总和为 m 的宝石。

一共有 n+1 种不同的宝石。第 i (1≤i≤n) 种宝石一共有 ai 颗,每一颗的体积都是 bi。第 n+1 种宝石有无限多颗,每一颗的体积都是 1。

现在蜗蜗想用数量最少的宝石装满口袋,请求出蜗蜗最少要使用多少颗宝石。
输入格式

第一行一个正整数 test 表示数据组数。

对于每组数据,第一行两个整数 n,m。接下来 n 行,每行两个整数 ai,bi 分别表示一种宝石的数量和体积。
输出格式

对于每组数据,输出一行一个整数,表示蜗蜗最少要使用多少颗宝石。
样例输入

2
2 7
1 2
1 4
2 6
1 2
1 4

样例输出

3
2

数据规模

对于 30% 的数据,保证所有的 ai=1。

对于 100% 的数据,保证 1≤test≤10^5,1≤n≤31,0≤m<2^31,1≤ai<2^31,2≤bi<2^31,bi 已经从小到大排好序了并且两两不同。

C++
这题目有点难,能否帮帮我

  • 写回答

1条回答 默认 最新

  • AICodeThunder 2023-10-02 13:25
    关注

    先读入数据,用一个数组 a 存储宝石数量,用一个数组 b 存储宝石体积。然后,用一个变量 sum 记录当前已经装入口袋的宝石体积总和,用一个变量 cnt 记录已经装入的宝石数量。接下来,遍历每种宝石,如果当前宝石体积加上 sum 小于等于口袋容量 m,则将该宝石体积加入 sum,并将 cnt 加 1;如果当前宝石体积加上 sum 大于 m,则需要判断是否能够舍弃当前宝石而使得 sum 更接近 m。具体来说,如果后面宝石的体积与当前宝石体积之差大于 m-sum,则舍弃当前宝石,否则需要判断左右两个区间的大小,并计算出需要舍弃的宝石数量。最后,输出 cnt 的值即可。下面是一个例子:

    #include <iostream>
    using namespace std;
    
    int main() {
        int test;
        cin >> test;
        while (test--) {
            int n, m;
            cin >> n >> m;
            int a[100005], b[100005];
            for (int i = 1; i <= n; i++) {
                cin >> a[i] >> b[i];
            }
            int sum = 0, cnt = 0;
            bool flag = false;
            for (int i = 1; i <= n; i++) {
                if (!flag && sum + b[i] <= m) {
                    sum += b[i];
                    cnt++;
                } else if (sum == m) {
                    break;
                } else {
                    flag = true;
                    if (i == n || b[i+1] - b[i] > m - sum) {
                        cnt++;
                        sum += b[i];
                    } else {
                        int diff = m - sum;
                        int left = i - 1, right = i + 1;
                        while (left >= 1 && b[left] - b[i] >= diff) left--;
                        while (right <= n && b[right] - b[i] >= diff) right++;
                        if (right - left >= 2) {
                            cnt += right - left - 1;
                        } else {
                            cnt++;
                        }
                        sum += b[i];
                    }
                }
            }
            cout << cnt << endl;
        }
        return 0;
    }
    
    
    评论

报告相同问题?

问题事件

  • 创建了问题 10月2日

悬赏问题

  • ¥20 c语言写的8051单片机存储器mt29的模块程序
  • ¥60 求直线方程 使平面上n个点在直线同侧并且距离总和最小
  • ¥50 java算法,给定试题的难度数量(简单,普通,困难),和试题类型数量(单选,多选,判断),以及题库中各种类型的题有多少道,求能否随机抽题。
  • ¥50 rk3588板端推理
  • ¥250 opencv怎么去掉 数字0中间的斜杠。
  • ¥15 这种情况的伯德图和奈奎斯特曲线怎么分析?
  • ¥250 paddleocr带斜线的0很容易识别成9
  • ¥15 电子档案元素采集(tiff及PDF扫描图片)
  • ¥15 flink-sql-connector-rabbitmq使用
  • ¥15 zynq7015,PCIE读写延时偏大