链接:
点击打开链接
题目描述
wyh学长现在手里有n个物品,这n个物品的重量和价值都告诉你,然后现在让你从中选取k个,问你在所有可能选取的方案中,最大的单位价值为多少(单位价值为选取的k个物品的总价值和总重量的比值)
输入描述:
输入第一行一个整数T(1<=T<=10) 接下来有T组测试数据,对于每组测试数据,第一行输入两个数n和k(1<=k<=n<=100000) 接下来有n行,每行两个是a和b,代表这个物品的重量和价值
输出描述:
对于每组测试数据,输出对应答案,结果保留两位小数
示例1
输入
1 3 2 2 2 5 3 2 1
输出
0.75
说明
对于样例来说,我们选择第一个物品和第三个物品,达到最优目的
解题思路:一开始我以为是背包问题,然后想到一种就是以物品个数当体积来使用,但是很快就被我pass了,因为你无法建立一个有效的方程。
然后我想到了贪心,但是WA了。然后我就卡了1个小时多,最后想到可以用二分试试。
二分平均数,让前k个选取的物品多余部分之后趋近0 这样的话,我们就能得到前k个物品的单位价值最大,
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn=1e5+10;
int n,m;
struct Node{
int va,we;
}node[maxn];
double yy[maxn];
bool check(double st){
memset(yy,0,sizeof(yy));
int i;
for(i=0;i<n;i++){
yy[i]=node[i].va-node[i].we*st;
}
sort(yy,yy+n);
double sum=0;
for(i=n-1;i>=n-m;i--){
sum+=yy[i];
}
return sum>=0;
}
int main(){
int i,j,t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
int tot1=0,tot2=0;
int wa,va;
double ma=0;
for(i=0;i<n;i++){
scanf("%d%d",&node[i].we,&node[i].va);
double te=1.0*node[i].va/node[i].we;
if(te>ma){
ma=te;
}
}
double l=0,r=ma,mid;
for(i=0;i<100;i++){
mid=(r+l)/2;
if(check(mid))
l=mid;
else
r=mid;
}
printf("%.2lf\n",l);
}
return 0;
}