P1577 切绳子(二分)
题目描述
有 N 条绳子,它们的长度分别为 Li。如果从它们中切割出 K 条长度相同的绳子,这 K 条绳子每条最长能有多长?答案保留到小数点后 2 位(直接舍掉 2 位后的小数)。
输入格式
第一行两个整数 N 和 K,接下来 N 行,描述了每条绳子的长度 Li 。
输出格式
切割后每条绳子的最大长度。答案与标准答案误差不超过 0.01 或者相对误差不超过 1% 即可通过。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int n, k;
double L[N]; // 用 double 存绳子长度
bool check(double x) { // 检查长度 x 是否可行,返回能切出的绳子数是否 >= k
int count = 0;
for (int i = 1; i <= n; i++) {
count += L[i] / x; // 每条绳子能切几段
}
return count >= k;
}
int main() {
cin >> n >> k;
double l = 0, r = 0;
for (int i = 1; i <= n; i++) {
cin >> L[i];
r += L[i];
}
r /= k; // 最大可能长度
double eps = 1e-4; // 精度 0.0001
while (r - l > eps) {
double mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
printf("%.2f", l);
return 0;
}
check 函数
检查能不能把每条绳子切成长度为 x
的段,然后看总共能不能切出至少 k
条。
当 r - l < eps
(两个边界非常接近)时,就说明我们找到了最接近的最大可能长度。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
ll n, k;
ll L[N];
bool check(ll x) {
ll count = 0;
for (int i = 1; i <= n; i++) {
count += L[i] / x;
}
return count >= k;
}
int main() {
cin >> n >> k;
ll l = 1, r = 0;
for (int i = 1; i <= n; i++) {
double temp;
cin >> temp;
L[i] = temp * 100;
r = max(r, L[i]);
}
ll ans = 0;
while (l <= r) {
ll mid = (l + r) / 2;
if (check(mid)) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
printf("%.2f", ans / 100.0);
return 0;
}
把浮点数×100 转为整数来处理
把最终整数结果除以100,保留两位小数