UVA 12124 Assemble(贪心 二分)

本文介绍了一个基于二分搜索算法的优化方案,用于在有限预算内组装个人电脑,并确保所选配件中品质最差的部件其品质因子尽可能高。通过删除低于设定阈值的配件并选择每种类别中最经济的选项来实现这一目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:

你有b块钱,想要组装一台电脑。给出n个配件各自的种类、品质因子和价格,要求每种类型的配件各买一个,总价格不超过b,且“品质最差配件”的品质因子应尽量大。
【输入格式】
输入的第一行为测试数据组数T(T≤100)。每组数据的第一行为两个正整数n(1≤
n≤1 000)和b(1≤b≤109),即配件的数目和预算;以下n行每行描述一个配件,依次为种类、名称、价格和品质因子。其中,价格为不超过106的非负整数;品质因子是不超过109的非负整数(越大越好);种类和名称则由不超过20个字母、数字和下划线组成。输入保证总是有解。
【输出格式】
对于每组数据,输出配件最小品质因子的最大值。

分析:

在《入门经典》一书中,我们曾提到过,解决“最小值最大”的常用方法是二分答案。假设答案为x,如何判断这个x是最小还是最大呢?删除品质因子小于x的所有配件,如果可以组装出一台不超过b元的电脑,那么标准答案ans≥x,否则ans<x。
如何判断是否可以组装出满足预算约束的电脑呢?很简单,每一类配件选择最便宜的一个即可。如果这样选都还超预算的话,就不可能有解了。

import java.util.*;

public class Main {
    static int cnt ,n, b;
    static HashMap<String,Integer> id = new HashMap<String,Integer>();
    static ArrayList<ArrayList<Component>> comps = null;
    static Integer ID(String s) {
        int res=0;
        if(id.containsKey(s)) {
            res=id.get(s);
        }else {
            id.put(s, cnt);
            res = cnt;
            cnt++;
        }
        return res;
    }
    static void init() {
        cnt = 0;
        id.clear(); //初始化id
        comps = new ArrayList<ArrayList<Component>>();
        for(int i=0;i <= n;i++) {
            ArrayList<Component> tmp =new ArrayList<Component>();
            comps.add(tmp);
        }
    }
    static boolean judge(int q) {
        int sum = 0;
        for(int i = 0; i < cnt; i++) {
            int cheapest = b + 1;
            for(int j = 0; j < comps.get(i).size(); j++) {
                if(comps.get(i).get(j).quality >= q)
                    cheapest = Math.min(cheapest, comps.get(i).get(j).price);
            }
            if(cheapest == b + 1) {
                return false;
            }
            sum += cheapest;
            if(sum > b) {
                return false;
            }
        }
        return true;
    }
    public static void main(String []args) {
        Scanner cin = new Scanner(System.in);
        int T;
        T = cin.nextInt();
        while(T-- > 0) {
            n = cin.nextInt();
            b = cin.nextInt();

            init();
            int maxq = Integer.MIN_VALUE , minq = Integer.MAX_VALUE;
            String type, name;
            int p , q;
            for(int i = 0; i < n; i++) {
                type = cin.next();
                name = cin.next();
                p = cin.nextInt();
                q = cin.nextInt();
                maxq = Math.max(maxq,q);
                minq = Math.min(minq,q);
                int num = ID(type);
                comps.get(num).add(new Component(p,q));
            }
            int left = minq , right = maxq;
            while(left < right) {
                int mid = left + (right - left + 1) / 2;
                if(judge(mid)) {
                    left = mid;
                }else {
                    right = mid - 1;
                }
            }
            System.out.printf("%d\n", left);
        }
    }
}

class Component {
    int price;
    int quality;
    Component(int p,int q) {
        this.price = p;
        this.quality = q;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值