您的位置:首页 > 其它

2017 浙工业院赛预赛 E 小米买东西【二分+贪心】

2017-12-19 00:00 246 查看
时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 131072K,其他语言262144K

64bit IO Format: %lld

题目描述

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

输入描述:

多组数据。

第一行一个整数T,为数据组数。

接下来有T组数据。

对于每组数据,第一行两个正整数n,k,如题。

接下来n行,每行有两个正整数ci,vi。分别为手办的花费和它对于小咪的价值。

输出描述:

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

示例1

输入

1

5 1

1 2

2 3

3 4

4 5

5 6

输出

2

备注:

1≤T≤10

1≤n≤104

1≤k≤n

1≤ci,vi≤104

分析:不得不说,上来的第一反应是动态规划亦或是背包之类的算法。而精度的控制又似乎是二分的套路。不得不说,拿着锤子的人看见什么都像钉子。这个题可以通过二分答案,按照 Vi−Ci∗mid 排序后,选择前 K 项累计求和与 0 求和即可判断。

注意:求和时会爆掉int的下限

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long int
const ll maxn = 1e5 + 10;
int n, k, T;
struct node {
int c, v;
}a[maxn];
int b[maxn];
bool cmp(int a, int b) {
return a > b;
}
int judge(int x)
{
long long int sum = 0;
for (int i = 1; i <= n; i++) {
b[i] = a[i].v-a[i].c*x;
}
sort(b + 1, b + n + 1, cmp);
for (int i = 1; i <= k; i++) {
sum += 1ll*b[i];
}
if (sum >= 0) return 1;
return 0;
}
int main()
{
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &k);
int max = 0;
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a[i].c,&a[i].v);
if (max < (a[i].v / a[i].c))
max = a[i].v / a[i].c;
}
int L = 0, R = max+1,mid;
while (L <= R)
{
mid = (L + R) / 2;
int tmp = judge(mid);
//if (tmp == 0) break;
if (tmp) L = mid + 1;
else R = mid - 1;
}
if (judge(mid))
printf("%d\n", mid);
else
printf("%d\n", mid - 1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: