现在的位置: 首页 > 综合 > 正文

例题1.12 组装电脑 UVa12124

2018年04月29日 ⁄ 综合 ⁄ 共 1548字 ⁄ 字号 评论关闭

1.题目描述:点击打开链接

2.解题思路:本题要求最小值最大化,一般方法是利用二分查找解决,即每次都枚举一个品质因子x,删除所有品质因子小于x的配件,如果可以组装出一台不超过b元的电脑,那么ans≥b,否则ans<b。那么如何判断是否可以组装出总价不超过b的电脑呢?很简单,只需要选择最便宜的一个即可,如果这样还超出预算,则无解。

本题需要防止TLE,在写二分搜索时候计算中点M时R-L要改为R-L+1,这样使得中点偏向R,以防止陷入死循环。在判断的时候进行适当的优化,比如设置一个cheapest变量表示最便宜的价格,初始为b+1,若枚举完该类型的所有配件后还是b+1,说明无法组装;另外可以在每次累加sum后判断是否已经超过b,如果超过,则无法组装。另外,本题有一个值得学习的地方:整个程序中关键的变量是类型编号,每个配件的价格和品质因子,因此类型名称就不需要保存了。

3.代码:

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

int cnt;
map<string, int>id;
int ID(string s)//给每种类型分配一个ID,由于本题关键的变量只有price和quality,因此无关的属性不需要保存
{
	if (!id.count(s))id[s] = cnt++;
	return id[s];
}
#define N 1000+5
struct Component
{
	int price;
	int quality;
};
int n, b;//组件的数目,预算
vector<Component>comp[N];
bool ok(int q)
{
	int sum = 0;
	for (int i = 0; i < cnt; i++)
	{
		int cheapest = b + 1, m = comp[i].size();
		for (int j = 0; j < m;j++)
		if (comp[i][j].quality >= q)
			cheapest = min(cheapest, comp[i][j].price);
		if (cheapest == b + 1)return false;
		sum += cheapest;
		if (sum>b)return false;
	}
	return true;
}

int main()
{
	//freopen("t.txt", "r", stdin);
	int T;
	cin >> T;
	while (T--)
	{
		cin >> n >> b;
		cnt = 0;
		for (int i = 0; i < n; i++)
			comp[i].clear();
		id.clear();
		int maxq = 0;
		for (int i = 0; i < n; i++)
		{
			char type[30], name[30];
			int p, q;
			scanf("%s%s%d%d", type, name, &p, &q);
			maxq = max(maxq, q);
			comp[ID(type)].push_back(Component{ p, q });
		}
		int L = 0, R = maxq;
		while (L < R)
		{
			int M = L + (R - L + 1) / 2;//注意,必须要加1,否则可能会无限死循环
			if (ok(M))L = M;
			else R = M - 1;
		}
		printf("%d\n", L);
	}
	return 0;
}

抱歉!评论已关闭.