礼物(贪心,枚举,二分)

题意

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

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

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

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

方便起见,Pi 一定是偶数。

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

数据范围

1N1000

思路

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

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

  1. 对于前x头牛,可以全选,对其中p最大的牛使用优惠券。
  2. 选择前x1头牛,然后将优惠券用到xnp/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;
}
posted @   pbc的成长之路  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示