题意
农夫约翰想给他的 \(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\)。这时有两种策略:
- 对于前\(x\)头牛,可以全选,对其中\(p\)最大的牛使用优惠券。
- 选择前\(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;
}