【貪心】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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章