硬件DIY秀
总提交:181 测试通过:30
描述
近期,计算机学院举办第四届学生课外科技节活动,硬件DIY秀活动使同学们组装电脑提高动手能力,主办方计算机学院分团委和科协决定购买电脑组件,每种类型的组件各需购买一个,并希望组装后的电脑能够实际使用。你的任务是帮助主办方最终确定购买何种性能组件,在最大限度地提高最低组件的性能,同时不能超过他们的预算。这里假设电脑的性能等同于其最薄弱组件的性能。
输入
第一行是一个正整数:测试用例数目,最多为100。之后,每个测试用例包括:
l 一行,含两个整数n,b:1≤n≤1000,表示组件的数目,1≤b≤1000000000,表示他们的预算。
l n行,按以下格式:“type name price quality”,type是一个字符串,表示组件的类型;name是一个字符串,表示组件的名称;price是一个整数(0≤price≤1000 000),表示组件的价格;quality是一个整数(0≤quality≤1000000000),表示组件的性能(越高越好)。字符串只能由字母和数字组成,最大长度为20个字符。
通常能够根据他们的预算来组装一台电脑。
输出
对于每个测试用例,输出包括:
l 一行,为一个整数:表示可能的最高性能。
样例输入
1
18 800
processor 3500_MHz 66 5
processor 4200_MHz 103 7
processor 5000_MHz 156 9
processor 6000_MHz 219 12
memory 1_GB 35 3
memory 2_GB 88 6
memory 4_GB 170 12
mainbord all_onboard 52 10
harddisk 250_GB 54 10
harddisk 500_FB 99 12
casing midi 36 10
monitor 17_inch 157 5
monitor 19_inch 175 7
monitor 20_inch 210 9
monitor 22_inch 293 12
mouse cordless_optical 18 12
mouse microsoft 30 9
keyboard office 4 10
样例输出
9
题目来源
南京邮电大学计算机学院首届ACM程序设计大赛(2009)
分析:首先看到以为是动态规划,后来以为是贪心算法。其实都不是,其实就是求最低性能的最大。可以用二分法解决。
有几个问题:一个是数据的输入与保存,还有就是比较的问题。
参考了别人的写法:
数据输入,例如processor 3500_MHz 66 5只需要组件的类别processor、价格66、性能5。3500_MHz忽略。注意代码中的
char useless[50];
类别可以用一个数组,值为类别递增(0,1,2,3...)。但是如何判断他们都是同一个组件类别(例如都是processor呢?)
这里可以采用C++的map容器,它提供1对1的关系。map下标为组件类别(processor、cpu、mouse等),对应的值为类别的数字表示(0,1,2,3...)。方便的可以使用enum,具体使用有待开发。
因为同一类组件有不同的个型号,所以保存在vector里面,vector相当于二维数组,p[x][y]:x对应组件的类别,y对应某一类别的不同的下标。
vector较方便的插入元素以及判断元素个数。
然后将每类组件的不同型号的价格price和性能quality分别插入p[no]和q[no]容器中。(no代表某一类型,根据输入的顺序递增)
(如processor为0、memory为1、mainbord为2。。。)
-------------------------------------------------------------------------------------------------------------------------------------------
接下来是如何最大限度地提高最低组件的性能,同时不能超过他们的预算。
采用类似二分法:
l为最小的性能(quality)值,r为最大的性能值。求l~r的符合要求的最大值。★输入的型号性能递增的,方便了二分查找。
while(l < r) // 最低的性能值 / 最大的性能值{int middle = l + (r-l+1)/2;if(fun(middle))l = middle;elser = middle - 1;}printf("%d\n",l);
讨论一下二分的判断条件,也就是fun函数:
bool fun(int middle)
{int sum = 0; // 总价格 <= bfor(int i=0;i<counts;i++) // 遍历所有类别{int low = 1100000000; // 单个组件的价格for(int j=0;j<q[i].size();j++) // p / q 的长度,一样的{if(q[i][j] < middle) continue;low = min(low, p[i][j]); // price价格}sum += low;if(1100000000 == low || sum > b) return false;}return true;
}
对于middle,它是待判断的性能值,如果true,继续从middle~r查找符合要求的最大的性能值,如果false,就从l~middle-1查找。
true的条件是存在性能比middle大的且总价格仍小于b的。这里需要遍历所有类别的所有型号。这个的构造还是很神奇的,效率也表较高。
当然,肯定还有更好的方法。