LA 3971 Assemble(组装电脑 最小值最大 二分答案)

本文介绍了一种使用二分查找算法解决计算机配件选择问题的方法。通过二分查找确定最佳品质因子,在预算范围内选择性价比最高的配件组合。

二分答案这个思想用过了。非常好的思想,题意是你有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;
}

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值