1257 揹包問題 V3(二分)
阿新 • • 發佈:2018-11-24
1257 揹包問題 V3
3 秒 131,072 KB 80 分 5 級題
題意 :
從n個物品中選出k個,使單位體積價值最大
思路:
一開始正面想,試過很多種,排序什麼的、、總是結果不對,最後想到二分答案
二分的規則是使index的前接近0即可
ps:blocks[i].w物體的價值
block[i].p物體的體積
p二分答案
假設p
是我們要的答案,那麼block[i].p*p
為block[i]
應該佔有的價值
blocks[i].w - block[i].p * p
為現在與目標價值的差
這個差約小說明越接近答案,根據這一位進行排序,只要前k個。記錄當前總體積和總價值即可。
import java.util.Arrays; import java.util.Scanner; public class Main { static int n, k; static int ansA = 0, tA = 0; static int ansB = 0, tB = 0; static Block[] blocks = null; public static void main(String[] args) { Scanner cin = new Scanner(System.in); n = cin.nextInt(); k = cin.nextInt(); blocks = new Block[n]; for (int i = 0; i < n; i++) { int a = cin.nextInt(); int b = cin.nextInt(); blocks[i] = new Block(a, b, 0); } cin.close(); double left = 0, right = 50000.0; for (int i = 1; i < 100; i++) { double mid = (left + right) / 2.0; if (check(mid)) { ansA = tA;ansB = tB;tA = tB = 0; left = mid; } else { ansA = tA;ansB = tB;tA = tB = 0; right = mid; } } int x = gcd(ansA, ansB); System.out.println(ansB / x + "/" + ansA / x); } public static boolean check(double p) { for (int i = 0; i < n; i++) { blocks[i].dis = 1.0 * blocks[i].w - blocks[i].p * p; } Arrays.sort(blocks); double sum = 0; for (int i = 0; i < k; i++) { tA += blocks[i].w; tB += blocks[i].p; sum += blocks[i].dis; } if (sum > 0) return true; return false; } static int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } static class Block implements Comparable<Block> { int w; int p; double dis; public Block(int w, int p, double dis) { this.w = w; this.p = p; this.dis = dis; } @Override public int compareTo(Block o) { if (dis > o.dis) return 1; return -1; } } }