题目描述
>小咪是一个土豪手办狂魔,这次他去了一家店,发现了好多好多(n个)手办,但他是一个很怪的人,每次只想买k个手办,而且他要让他花的每一分钱都物超所值,即:买下来的东西的总价值/总花费=max。请你来看看,他会买哪些东西吧。
输入描述:
>多组数据。
第一行一个整数T,为数据组数。
接下来有T组数据。
对于每组数据,第一行两个正整数n,k,如题。
接下来n行,每行有两个正整数ci,vi。分别为手办的花费和它对于小咪的价值。
输出描述:
>对于每组数据,输出一个数,即能得到的总价值/总花费的最大值。精确至整数。
备注:
>1≤T≤10
1≤n≤104
1≤k≤n
1≤ci,vi≤104
题解
这应该也是01分数规划的裸题。
https://blog.nowcoder.net/n/c0e93d646a8c4d71a6ef03fcebc6359b
我在这篇博客中详细介绍了怎么用二分去求解01分数规划。
这道题对比那道题只不过是把实数二分换成了整数二分...我也没搞明白为啥他有4颗小星星。
这种题还可以再简单拓展一下,即不给出k让我们求最大值,思想也很简单,就是排完序后原来是把前k个加到一起判是否大于0,现在我们只需要看有没有大于0的即可了~
完整代码
#include<bits/stdc++.h> using namespace std; pair<int,int> a[10050]; int n,k; int c[10050]; bool check(int x){ for(int i=1;i<=n;++i){ c[i]=a[i].second-x*a[i].first; } sort(c+1,c+1+n); double sum=0; for(int i=n;i>n-k;--i){ sum+=c[i]; } return sum>=0; } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&k); for(int i=1;i<=n;++i)scanf("%d%d",&a[i].first,&a[i].second); int l=0,r=1e4; int ans; while(l<=r){ int mid=(l+r)>>1; if(check(mid))ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); } }
(感觉自己这篇题解写的好水嘤嘤嘤)