一、Problem
窗外肉价飞涨,屋里灶台微响。便当店老板在沉思中苦恼: 现在店里的存货还有nn条特制香肠,长度分别为
如果能从它们中切割出 k 条长度相同的香肠的话,就能应付突如其来的奇怪的订单
你能帮这位老板计算一下这 k 条香肠每条最长能有多长吗?
(答案保留小数点后两位,规定1 单位长度的香肠最多可以切割成 100 份)
输入
3 4
3 5 4
输出
2.50
样例解释
第一根和第三根分别裁剪出一根2.50长度的绳子,第二根剪成2根2.50长度的绳子,刚好4根。
二、Solution
方法一:暴力
- 可选的长度一定在香肠长度区间 中,所以我们可以通过枚举这里面的区间中的每一个浮点数确定长度
- 从大到小枚举,第一次可以将所有香肠一共切成 k 份的长度就是所求长度。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Solution {
double[] L;
int n, k;
boolean check(double l) {
int cnt = 0;
for (int i = 0; i < n; i++) {
int t = (int) (L[i] / l);
cnt += t;
if (cnt >= k)
return true;
}
return false;
}
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
n = sc.nextInt();
k = sc.nextInt();
L = new double[n];
for (int i = 0; i < n; i++) L[i] = sc.nextDouble();
Arrays.sort(L);
double max = L[n-1];
for (double i = max; i >= 0.01; i -= 0.01) {
if (check(i)) {
System.out.printf("%.2f", i);
return;
}
}
}
}
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}
复杂度分析
- 时间复杂度:,
- 空间复杂度:,
方法二:二分
- ,最小切分长度为 1
- 当 mid 满足切分要求时,应该贪心地右移左边界,因为可能会有更大 mid 在 l 的右边。
2/20?什么情况… 看上去没什么问题啊,都转为了整形,然后最后也转为了浮点数输出了…
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Solution {
int[] L;
int n, k;
boolean check(double l) {
int cnt = 0;
for (int i = 0; i < n; i++) {
int t = (int) (L[i] / l);
cnt += t;
if (cnt >= k)
return true;
}
return false;
}
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
n = sc.nextInt();k = sc.nextInt();L = new int[n];
for (int i = 0; i < n; i++) L[i] = (int)sc.nextDouble() * 100;
Arrays.sort(L);
int l = 1, r = L[n-1], res = 0;
while (l <= r) {
int mid = (l + r) >>> 1;
if (check(mid)) {
l = mid+1;
res = mid;
} else {
r = mid-1;
}
}
System.out.printf("%.2f", 1.0 * res / 100);
}
}
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}
老毛病,hh:输入的时候先把浮点数转为整形,然后乘以 100,就算对了,也不好意思吧…
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Solution {
int[] L;
int n, k;
boolean check(int l) {
int cnt = 0;
for (int i = 0; i < n; i++) {
cnt += L[i] / l;
if (cnt >= k)
return true;
}
return false;
}
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
n = sc.nextInt();k = sc.nextInt();L = new int[n];
int l = 1, r = 0, res = 0;
for (int i = 0; i < n; i++) {
L[i] = (int)(sc.nextDouble() * 100);
r = Math.max(L[i], r);
}
while (l <= r) {
int mid = (l + r) >>> 1;
if (check(mid)) {
l = mid + 1;
res = mid;
} else {
r = mid - 1;
}
}
System.out.printf("%.2f", 1.0 * res / 100);
}
}
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}
复杂度分析
- 时间复杂度:,
- 空间复杂度:,