1. 程式人生 > >1257 揹包問題 V3(二分)

1257 揹包問題 V3(二分)

1257 揹包問題 V3
3 秒 131,072 KB 80 分 5 級題

題意 :

從n個物品中選出k個,使單位體積價值最大

思路:

一開始正面想,試過很多種,排序什麼的、、總是結果不對,最後想到二分答案


二分的規則是使index的前接近0即可

ps:blocks[i].w物體的價值 block[i].p物體的體積 p二分答案

假設p是我們要的答案,那麼block[i].p*pblock[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;
        }
    }
}