题目链接: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);
}
}
}