【贪心】B033_LQ_切香肠(暴力 / 二分)

一、Problem

窗外肉价飞涨,屋里灶台微响。便当店老板在沉思中苦恼: 现在店里的存货还有nn条特制香肠,长度分别为 LiL_i

​如果能从它们中切割出 k 条长度相同的香肠的话,就能应付突如其来的奇怪的订单

你能帮这位老板计算一下这 k 条香肠每条最长能有多长吗?

(答案保留小数点后两位,规定1 单位长度的香肠最多可以切割成 100 份)

输入
3 4
3 5 4

输出
2.50

样例解释
第一根和第三根分别裁剪出一根2.50长度的绳子,第二根剪成2根2.50长度的绳子,刚好4根。

二、Solution

方法一:暴力

  • 可选的长度一定在香肠长度区间 [minlmaxl][min_l,max_l] 中,所以我们可以通过枚举这里面的区间中的每一个浮点数确定长度
  • 从大到小枚举,第一次可以将所有香肠一共切成 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();
    }
}

复杂度分析

  • 时间复杂度:O(max(L[0...N]))O(max(L[0...N]))
  • 空间复杂度:O(1)O(1)

方法二:二分

  • l=1r=max(Li)l = 1,r = max(L_i),最小切分长度为 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();
    }
}

复杂度分析

  • 时间复杂度:O(logMax)O(logMax)
  • 空间复杂度:O(1)O(1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章