题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3276
题目大意:有b块的预算,要组装一台电脑,给出n个配件,每个配件标明种类,名称,品质和价格,要求每种配件各买一个,从价格不超过b,且品质最低的配件的品质尽可能大。输出最小品质配件的品质。
解题关键:“最小值最大”问题常用方法是二分法,对所有配件的品质进行二分。假设二分得到的值为x,在每种配件中选择品质大于等于x的最便宜配件,若最后花费<b则ans>=x,否则ans<x.
import java.util.*; class Component { String name; int price; int quality; public Component(String name,int price,int quality) { this.name=name; this.price=price; this.quality=quality; } } public class Main { static int n,b; static int count; static Map<String,Integer> kind_num=new HashMap<String,Integer>(); static ArrayList<ArrayList<Component>> comp=null; static int ID(String type) { int res=0; if(kind_num.containsKey(type)) { res=kind_num.get(type); } else { kind_num.put(type, count); res=count; count++; } return res; } static int min(int a,int b) { return a<b?a:b; } static boolean OK(int M) { int sum=0; for(int i=0;i<count;i++) { ArrayList<Component> temp=comp.get(i); int cheapest=b+1; for(int j=0;j<temp.size();j++) { if(temp.get(j).quality>=M) cheapest=min(cheapest,temp.get(j).price); } if(cheapest==b+1) return false; sum=sum+cheapest; if(sum>b) return false; } return true; } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int t; Scanner in=new Scanner(System.in); t=in.nextInt(); for(;t>0;t--) { kind_num.clear(); n=in.nextInt(); b=in.nextInt(); comp=new ArrayList<ArrayList<Component>>(); for(int i=0;i<n;i++) { ArrayList<Component> tem=new ArrayList<Component>(); comp.add(tem); } int type_num=0; count=0; int max=Integer.MIN_VALUE,min=Integer.MAX_VALUE; for(int i=0;i<n;i++) { String type=in.next(); String name=in.next(); int price=in.nextInt(); int quality=in.nextInt(); if(quality>=max) max=quality; if(quality<min) min=quality; int num=ID(type); Component temp=new Component(name,price,quality); comp.get(num).add(temp); } int L=min,R=max; while(L<R) { int M=L+(R-L+1)/2; if(OK(M)) { L=M; } else { R=M-1; } } System.out.println(L); } } }