吊桥1

GitHub跳转原题关系图返回列表

排序后双指针:每趟让最重的史莱姆与最轻的能同乘就配对,趟数即最短时间,O(n log n)。

OJ: roj

题目 ID: 20009

难度:入门

标签:入门贪心排序python

创建: 2026-10-02 19:40

更新: 2026-10-06 08:59

题目描述

nn 只史莱姆要过一座吊桥,桥的最大载重为 CC,每次最多同时过 2 只(也可 1 只独过),同一趟上的史莱姆重量和不得超过 CC;每只过桥时间都是 11,求所有史莱姆过完的最短时间。

输入格式:第一行两个数 nn 和 CC;第二行 nn 个数,表示每只史莱姆的重量。

输出格式:一个数,最短的过桥时间。

输入样例(n=5n=5、C=10C=10,重量 1,2,3,4,51,2,3,4,5):

text
5 10
1 2 3 4 5

输出样例:3(由输入样例得到)。

数据范围:1≤n≤1051 \leq n \leq 10^5。

思路

每趟耗时恒为 1,最短时间即最少趟数:把重量升序排序后用双指针,最重的一只必须走,若它加上当前最轻的不超过 CC 就同乘一趟,否则独占一趟。能配就配不劣于最优(趟数 =n−=n- 配对数),时间复杂度 O(nlog⁡n)O(n \log n)。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-02 19:41
# update_at: 2026-10-02 19:41

import sys


def solve() -> None:
    data = iter(map(int, sys.stdin.buffer.read().split()))
    n = next(data)                    # 史莱姆数量
    cap = next(data)                  # 吊桥最大载重
    weight = sorted(next(data) for _ in range(n))    # 排序后最轻/最重才在两端

    # 最重的必须过桥:能和最轻的挤一趟就同乘,否则独占一趟。
    # 每趟耗时都是 1,趟数 = n - 成功同乘的对数,一趟最多消化两只。
    light, heavy = 0, n - 1
    trips = 0
    while light <= heavy:
        trips += 1
        if weight[light] + weight[heavy] <= cap:
            light += 1                 # 最轻的搭上这趟,向内收一格
        heavy -= 1                     # 最重的总是从这趟离开
    print(trips)


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-06 08:59
 * update_at: 2026-10-06 08:59
 */
#include <cstdio>
#include <algorithm>

typedef long long ll;

const int MAXN = 100005;

int n;              // 史莱姆数量
ll cap;             // 吊桥最大载重
ll a[MAXN];         // 每只史莱姆的重量

int main() {
    scanf("%d %lld", &n, &cap);
    for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    std::sort(a + 1, a + n + 1);

    // 最重的必须过桥:能和最轻的挤一趟就同乘,否则独占一趟。
    // 每趟耗时都是 1,趟数 = n - 成功同乘的对数,一趟最多消化两只。
    int light = 1, heavy = n;
    ll trips = 0;
    while (light <= heavy) {
        trips++;
        if (a[light] + a[heavy] <= cap)
            light++;       // 最轻的搭上这趟,向内收一格
        heavy--;           // 最重的总是从这趟离开
    }
    printf("%lld\n", trips);
    return 0;
}