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;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值