最优河堤加固(二分答案 + 前缀和)

题目描述

给定各段河堤高度 heights[i],预算 MaxCosts,每车最大载量 MaxCapacity,每车运输成本 TransportationCostPerShipment,每单位土填埋成本 UnitCost。求在预算内能使所有河堤最低高度的最大值达到多少(可以超过原最大高度)。

输入描述

依次输入预算、车载量、运输成本、单位填埋成本、河堤数、高度数组。

输出描述

加固后的最大最低高度。

示例

输入:

text

复制代码
100 10 5 2 5
1 2 5 3 4

输出:

text

复制代码
11

解题思路

排序高度并求前缀和。二分目标高度 H,计算所需土量:找到第一个高度 ≥ H 的位置 k(lower_bound),所需土量为 H*k - prefix[k]。总成本 = 土量×填埋成本 + ceil(土量/载量)×运输成本。若 ≤ 预算则可行,向右收缩;否则向左。二分用上取整防止死循环。

C 语言代码

c

复制代码
#include <stdio.h>
#include <stdlib.h>

int cmp_ll(const void *a, const void *b) {
    long long x = *(const long long *)a, y = *(const long long *)b;
    return (x > y) - (x < y);
}

int main(void) {
    long long MaxCosts, MaxCapacity, TransCost, UnitCost;
    int n;
    if (scanf("%lld %lld %lld %lld %d", &MaxCosts, &MaxCapacity,
              &TransCost, &UnitCost, &n) != 5) return 0;

    long long *h = (long long *)malloc(sizeof(long long) * n);
    for (int i = 0; i < n; i++) scanf("%lld", &h[i]);

    qsort(h, n, sizeof(long long), cmp_ll);

    /* 前缀和 prefix[i] = h[0..i-1] 之和,prefix[0]=0 */
    long long *prefix = (long long *)malloc(sizeof(long long) * (n + 1));
    prefix[0] = 0;
    for (int i = 0; i < n; i++) prefix[i + 1] = prefix[i] + h[i];

    /* 二分上界:把全部填到 max + 预算/单位成本 即可 */
    long long lo = h[0], hi = h[n - 1] + MaxCosts / (UnitCost > 0 ? UnitCost : 1) + 1;

    while (lo < hi) {
        long long mid = lo + (hi - lo + 1) / 2; /* 上取整,避免死循环 */

        /* 找第一个 >= mid 的位置 k(lower_bound) */
        int l = 0, r = n; /* [l, r) */
        while (l < r) {
            int m2 = (l + r) / 2;
            if (h[m2] >= mid) r = m2;
            else l = m2 + 1;
        }
        int k = l;

        /* 需要填埋的土量:mid*k - prefix[k] */
        long long soil = mid * (long long)k - prefix[k];

        /* 运输车数:ceil(soil / MaxCapacity) */
        long long cars = (soil + MaxCapacity - 1) / MaxCapacity;

        long long cost = soil * UnitCost + cars * TransCost;

        if (cost <= MaxCosts) lo = mid;   /* 可行,尝试更高 */
        else hi = mid - 1;                /* 不可行,降低 */
    }

    printf("%lld\n", lo);

    free(h); free(prefix);
    return 0;
}
相关推荐
171320330计算机毕设编程1 小时前
计算机毕业设计 基于Hadoop的新能源汽车发展前景分析 LW PPT
java·大数据·hadoop·python·算法·随机森林·线性回归
垆边人似月.2 小时前
幻兽防御战(贪心算法)
数据结构·算法
DongQiShanRen2 小时前
六根硬件映射(下):物理闭环五步法,抽一条已实装的看
大数据·jvm·人工智能·算法·rust·哈希算法·集成学习
Code_Solitude2 小时前
c语言:指针(3)+冒泡排序
java·c语言·算法
FPGA信号处理2 小时前
【模式识别】第四节课:支持向量机
算法·机器学习·支持向量机
碧海银沙音频科技研究院2 小时前
面向长尾音频分类的知识蒸馏研究
人工智能·算法·音视频
alphaTao3 小时前
LeetCode 每日一题 2026/10/12-2026/10/18
算法·leetcode
青岚_Nox3 小时前
# C语言实战:函数完全指南——从基础概念到static/extern深度解析
算法
CCCCCCCCharlie3 小时前
深入解析I/O底层:文件描述符与缓冲区真相
linux·开发语言·c++·算法