题目描述
小明有 n 块木板,第 i ( 1 ≤ i ≤ n ) 块木板长度为 ai。
小明买了一块长度为 m 的木料,这块木料可以切割成任意块,拼接到已有的木板上,用来加长木板。
小明想让最短的模板尽量长。请问小明加长木板后,最短木板的长度可以为多少?
输入描述
输入的第一行包含两个正整数, n ( 1 ≤ n ≤ 10^3 ), m ( 1 ≤ m ≤ 10^6 ),n 表示木板数, m 表示木板长度。
输入的第二行包含 n 个正整数, a1, a2,…an ( 1 ≤ ai ≤ 10^6 )。
输出描述
输出的唯一一行包含一个正整数,表示加长木板后,最短木板的长度最大可以为多少?
用例
输入 | 5 3 4 5 3 5 5 |
输出 | 5 |
说明 | 给第1块木板长度增加1,给第3块木板长度增加2后, 这5块木板长度变为[5,5,5,5,5],最短的木板的长度最大为5。 |
输入 | 5 2 4 5 3 5 5 |
输出 | 4 |
说明 | 给第3块木板长度增加1后,这5块木板长度变为[4,5,4,5,5],剩余木料的长度为1。此时剩余木料无论给哪块木板加长,最短木料的长度都为4。 |
问题分析
-
题目理解:
- 给定 nnn 块木板,每块木板的长度为 aia_iai。
- 购买了一块长度为 mmm 的木料,可以将其切割成任意块并添加到已有的木板上。
- 目标是使得最短的木板尽量长,求出加长木板后,最短木板的最大长度。
-
输入描述:
- 第一行包含两个正整数 nnn 和 mmm。
- 第二行包含 nnn 个正整数 a1,a2,…,ana_1, a_2, \ldots, a_na1,a2,…,an。
-
输出描述:
- 输出一个整数,表示加长木板后,最短木板的最大长度。
-
解题思路:
- 排序:先对木板长度数组进行排序。
- 二分查找:通过二分查找尝试找到最短木板的最大长度。假设当前检查的长度为 midmidmid,计算将所有小于 midmidmid 的木板增加到 midmidmid 所需的总长度,并检查是否不超过 mmm。
- 验证:对于每一个二分查找的中点值,计算当前需要的木料量,判断是否满足条件。
C++ 代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool canAchieveLength(vector<int>& boards, int n, int m, int mid) {
int requiredWood = 0;
for (int i = 0; i < n; ++i) {
if (boards[i] < mid) {
requiredWood += (mid - boards[i]);
}
if (requiredWood > m) {
return false;
}
}
return true;
}
int maxMinLength(vector<int>& boards, int n, int m) {
sort(boards.begin(), boards.end());
int left = boards[0], right = boards[n-1] + m;
int result = left;
while (left <= right) {
int mid = left + (right - left) / 2;
if (canAchieveLength(boards, n, m, mid)) {
result = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
}
int main() {
int n, m;
cin >> n >> m;
vector<int> boards(n);
for (int i = 0; i < n; ++i) {
cin >> boards[i];
}
cout << maxMinLength(boards, n, m) << endl;
return 0;
}
Python 代码
def can_achieve_length(boards, n, m, mid):
required_wood = 0
for board in boards:
if board < mid:
required_wood += (mid - board)
if required_wood > m:
return False
return True
def max_min_length(boards, n, m):
boards.sort()
left, right = boards[0], boards[-1] + m
result = left
while left <= right:
mid = left + (right - left) // 2
if can_achieve_length(boards, n, m, mid):
result = mid
left = mid + 1
else:
right = mid - 1
return result
if __name__ == "__main__":
n, m = map(int, input().split())
boards = list(map(int, input().split()))
print(max_min_length(boards, n, m))
运行示例
假设输入如下:
5 3
4 5 3 5 5
运行上述程序可以得到输出:
5
这表示在给定的条件下,最短木板的最大长度可以达到 5。