二分答案这个思想用过了。非常好的思想,题意是你有b元钱 需要组装一台电脑
先给出n和b 分别代码有n个配件可供选择 一共有b元钱
接下来n行 每行描述一个配件 种类名 名称 价格 品质因子 品质因子越大越好 种类和名称是字符串
要求每个种类选一个
输出最小品质因子的最大值。
这个值肯定在品质因子的最小值和最大之间 二分这个答案
每次二分到的mid 查看是否ok ok就表示 对于每种配件 选择一个 比mid大或者等于mid的配件 price总数是不超过b的 也就是这种是可行的 但是不一定是最优的
最优还要考二分
这里用到的二分和平时常用的二分模板不一样 首先while循环里 是low<high 不是<= 否则一直死循环。。
因为我们最后得到的答案是low 而且mid 也用 mid=low+(high-low+1)/2; 的方法来求
所以 low 肯定是ok的 如果 新的mid 不ok low 也不能变。只能更新hign
因为如果mid不ok 肯定得比mid小的 所以high是mid-1
还有对于每种配件sort 按照价格排序 贪心思想 尽量找 品质满足 而且价格便宜的 如果没找到 直接return false;
最后看sum
其中用map <string,int> 把种类转换成数字 还有配件的名字在这里是没用的。因为没有要求选用了哪些配件
wa了一次 又是忘记把中间输出注释掉了。。。。
#include<iostream>
#include<cstdio>
#include<vector>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
const int maxn=1005;
struct Node
{
int quality;
int price;
bool operator <(const Node & n)const
{
return price<n.price;
}
};
map<string,int> mp;
vector<Node> vec[maxn];
int cnt,n,b;
bool ok(int m)
{
int i,j,sum=0;
for(i=0;i<cnt;++i)
{
bool f=0;
for(j=0;j<vec[i].size();++j)
{
if(vec[i][j].quality>=m)
{
f=1;
sum+=vec[i][j].price;
if(sum>b)
return false;
break;
}
}
if(!f)
return false;
}
return true;
}
int main()
{
int T;scanf("%d",&T);
char kind[25],name[25];
Node node;
while(T--)
{
mp.clear();
for(int i=0;i<maxn;++i)
vec[i].clear();
cnt=0;
scanf("%d %d",&n,&b);
int minquality=1<<29,maxquality=-1;
for(int i=0;i<n;++i)
{
scanf("%s %s %d %d",kind,name,&node.price,&node.quality);
if(!mp.count(string(kind)))
mp[string(kind)]=cnt++;
int k=mp[string(kind)];
vec[k].push_back(node);
minquality= min(minquality,node.quality);
maxquality= max(maxquality,node.quality);
}
for(int i=0;i<cnt;++i)
sort(vec[i].begin(),vec[i].end());
int low=minquality,high=maxquality,mid;
while(high>low)
{
mid=low+(high-low+1)/2;
if(ok(mid))
low=mid;
else
high=mid-1;
}
printf("%d\n",low);
}
return 0;
}