LA3871二分最大最小值

本文介绍了一道算法题的解决思路,通过二分法在限定预算内寻找最大品质因子的电脑组件组合。讨论了使用二分法加速查找过程的方法,并分享了具体的代码实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:点击这里

解题思路

此题题目描述的很简单,就是让我们用有限的预算找到最小品质因子最大的电脑组件,并且每种组件必须都要买。这种求“最小值最大”的常用方法就是二分:若猜想的答案为 x x ,则取所有品质因子大于x的组件进行组装,如果能不超过预算,则说明正确答案 >=x >= x 。因此,我们只需要枚举所有的品质因子,当第一个不满足题意的 x x 出现时,则解题结束。
但需要注意,此题有时间限制,因此必须使用二分法进行,时间复杂度为O(lgn)

代码实现

注意点

  1. 此题涉及到type,name,price,quality,比较复杂,可使用map进行hash,再给每个类型的组件一个vector,price和quality使用结构体进行存储。
  2. 需熟练使用map的各种函数。

待解决

  1. 在代码中已经表明,如果去掉if(cheapest == budget)这句话,则不能AC,显示为wrong answer,初步猜想是由于如果品质因子太大导致sum太大超出了int表示范围。
  2. 在代码中进行二分查找时,使用int middle = (right+left)/2则显示超时,为什么?
  3. 可将质量因子先排好序,再用二分查找进行枚举,可能会更快。

代码示例

#include <iostream>
#include <vector>
#include <map>
using namespace std;

const int maxn  = 1000 + 10;
int cnt = 0;

int  n; //预算和组件数目
int budget;

struct Compont {
    int price;
    int quality;
};


std::vector<Compont> comp[maxn]; //每一项都是vector的数组
std::map<string, int> ID;

int convert(string type)
{
    if (!ID.count(type))
    {   //如果还没有这个类型的组件
        ID[type] = cnt++;
    }
    return ID[type];
}

//看品质不小于q的组件是否能在预算范围内组装
bool judge(int q)
{
    int  sum = 0;
    for (int i = 0 ; i < cnt; i++)
    {
        int cheapest = budget;
        int m = comp[i].size();
        for (int j = 0; j < m; j++)
        {
            if (comp[i][j].quality >= q)
                cheapest = min(cheapest, comp[i][j].price);
        }
        sum += cheapest;
        //若没加这一句,则不能AC
        if(cheapest == budget)
            return false;

        if (sum > budget)
            return false;
    }
    return true;
}


int main()
{
    int N;
    cin >> N;
    while (N--)
    {
        cin >> n >> budget;
        cnt = 0;
        for (int i = 0 ; i < n ; i++)
        {
            comp[i].clear();
        }
        ID.clear();
        int maxq = 0;
        for (int i  = 0 ; i < n; i++)
        {
            string type, name;
            int p, q;
            cin >> type >> name >> p >> q;
            maxq = max(maxq, q);
            comp[convert(type)].push_back((Compont) {p, q});
        }

        //使用二分法来加快速度
        int left = 0,right = maxq;
        while (left < right)
        {
            int middle = (right+left+1)/2 ;
            //int middle = (right+left)/2 ; 为什么不可以?
            if (judge(middle))
                left = middle;
            else
            {
                right = middle - 1;
            }
        }
        cout << left << endl;
    }
    return 0;
}

欢迎关注我的个人博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值