• 礼物(枚举,二分)


    题意

    农夫约翰想给他的 \(N\) 头奶牛购买礼物,但是他的预算只有 \(B\) 元。

    奶牛 \(i\) 希望获得的礼物的价格为 \(P_i\),运输成本为 \(S_i\),也就是说约翰要帮奶牛 \(i\) 买礼物,共需花费 \(P_i+S_i\) 元钱。

    约翰有一张特殊的优惠券,如果使用该优惠券来订购一份礼物,那么该礼物的价格会变为只有正常价格的一半。

    如果约翰用该优惠券给奶牛 \(i\) 买礼物,那么他只需要支付 \(P_i/2+S_i\) 元钱。

    方便起见,\(P_i\) 一定是偶数。

    请帮助约翰确定他最多可以给多少头奶牛购买礼物。

    数据范围

    \(1 \leq N \leq 1000\)

    思路

    • 法一:枚举
      先按照不优惠的价格,对牛升序排列。然后枚举对哪头牛使用优惠券即可。

    • 法二:二分
      先按照不优惠的价格,对牛升序排列。二分查找可以买多少头牛,假设当前查找到的值为\(x\)。这时有两种策略:

    1. 对于前\(x\)头牛,可以全选,对其中\(p\)最大的牛使用优惠券。
    2. 选择前\(x - 1\)头牛,然后将优惠券用到\(x \sim n\)\(p/2+s\)最小的牛。
      这两种策略中最小值如果不超过\(B\),则可以买到\(x\)头牛。

    代码

    • 枚举
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 1010;
    
    int n, m;
    
    struct Cow
    {
        int p, s;
        int total;
        
        bool operator < (const Cow &t) const
        {
            return total < t.total;
        }
    }cow[N];
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i ++) {
            int p, s;
            scanf("%d%d", &p, &s);
            cow[i] = {p, s, p + s};
        }
        int ans = 0;
        sort(cow + 1, cow + n + 1);
        for(int i = 1; i <= n; i ++) {
            int t = cow[i].p / 2 + cow[i].s;
            if(t > m) continue;
            int num = 1;
            for(int j = 1; j <= n; j ++) {
                if(j == i) continue;
                if(t + cow[j].total > m) break;
                t += cow[j].total;
                num ++;
            }
            ans = max(num, ans);
        }
        printf("%d\n", ans);
        return 0;
    }
    
    • 二分
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    const int N = 1010;
    
    int n, m;
    
    struct Cow
    {
        int p, s;
        int total;
        
        bool operator < (const Cow &t) const
        {
            return total < t.total;
        }
    }cow[N];
    
    bool check(int x)
    {
        int mx = 0, mi = 2e9;
        for(int i = 1; i <= n; i ++) {
            if(i <= x) mx = max(mx, cow[i].p / 2);
            else mi = min(mi, cow[i].p / 2 + cow[i].s);
        }
        ll sum = 0;
        for(int i = 1; i <= x; i ++) sum += cow[i].total;
        if(sum - mx <= m) return true;
        if(sum - cow[x].total + mi <= m) return true;
        return false;
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i ++) {
            int p, s;
            scanf("%d%d", &p, &s);
            cow[i] = {p, s, p + s};
        }
        sort(cow + 1, cow + n + 1);
        int l = 0, r = n;
        while(l < r) {
            int mid = l + r + 1 >> 1;
            if(check(mid)) l = mid;
            else r = mid - 1;
        }
        printf("%d\n", l);
        return 0;
    }
    
  • 相关阅读:
    Java WebSocket通信Demo
    JAVA FTP/SFTP 上传下载文件
    SpringMVC+MyBatis 事务中 基于注解的声明式事务
    Java 调用支付宝接口
    linux安装Tomcat
    使用cxf发布restful的webservice
    restful的webservice
    oracle时间比较和分页查询
    jenkins问题
    linux安装jenkins
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/16220656.html
Copyright © 2020-2023  润新知