NC14662 小咪买东西

题目

题目描述

小咪是一个土豪手办狂魔,这次他去了一家店,发现了好多好多( n 个)手办,但他是一个很怪的人,每次只想买 k 个手办,而且他要让他花的每一分钱都物超所值,即:买下来的东西的总价值/总花费= max 。请你来看看,他会买哪些东西吧。

输入描述

多组数据。
第一行一个整数 T,为数据组数。
接下来有 T 组数据。
对于每组数据,第一行两个正整数 nk ,如题。
接下来 n 行,每行有两个正整数 civi 。分别为手办的花费和它对于小咪的价值。

输出描述

对于每组数据,输出一个数,即能得到的总价值/总花费的最大值。精确至整数。

示例1

输入

1
5 1
1 2
2 3
3 4
4 5
5 6

输出

2

备注

1T10
1n104
1kn
1ci,vi104

题解

知识点:01分数规划。

01分数规划的模板题。注意到,小于最优解的答案一定有一种方案大于等于它,大于最优解的答案不存在方案可行,符合用二分答案求解的要求(唯一零点,单调性)。我们先确定一个答案 mid ,若 mid 小于等于最优答案,则存在方案满足如下公式:

vicimidvimidci(vimidci)0

每次检验把 vimidci 从大到小排序,选前 k 大加和判断 (vimidci)0 ,若满足则小于等于答案,否则大于答案。

时间复杂度 O(nlogn+k)

空间复杂度 O(n)

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n, k;
int c[10007], v[10007], cv[10007];
bool check(int mid) {
for (int i = 0;i < n;i++) cv[i] = v[i] - mid * c[i];
sort(cv, cv + n, [&](int a, int b) {return a > b;});
long long sum = 0;
for (int i = 0;i < k;i++) sum += cv[i];
return sum >= 0;
}
bool solve() {
cin >> n >> k;
for (int i = 0;i < n;i++) cin >> c[i] >> v[i];
int l = 0, r = 1e4;
while (l <= r) {
int mid = l + r >> 1;
if (check(mid)) l = mid + 1;
else r = mid - 1;
}
cout << r << '\n';
return true;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}
posted @   空白菌  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示