硬件DIY秀

44 篇文章 1 订阅

硬件DIY秀

时间限制(普通/Java):1000MS/3000MS          运行内存限制:65536KByte
总提交:181            测试通过:30

描述

近期,计算机学院举办第四届学生课外科技节活动,硬件DIY秀活动使同学们组装电脑提高动手能力,主办方计算机学院分团委和科协决定购买电脑组件,每种类型的组件各需购买一个,并希望组装后的电脑能够实际使用。你的任务是帮助主办方最终确定购买何种性能组件,在最大限度地提高最低组件的性能,同时不能超过他们的预算。这里假设电脑的性能等同于其最薄弱组件的性能。

输入

第一行是一个正整数:测试用例数目,最多为100。之后,每个测试用例包括:

l         一行,含两个整数nb: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;
			else
				r = middle - 1;
		}
		printf("%d\n",l);


讨论一下二分的判断条件,也就是fun函数:

bool fun(int middle)
{
	int sum = 0; // 总价格 <= b
	for(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的。这里需要遍历所有类别的所有型号。这个的构造还是很神奇的,效率也表较高。

当然,肯定还有更好的方法。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值