题目描述
给定各段河堤高度 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;
}