Yougth的最大化
时间限制:1000 ms | 内存限制:65535 KB
难度:4
-
描述
-
Yougth现在有n个物品的重量和价值分别是Wi和Vi,你能帮他从中选出k个物品使得单位重量的价值最大吗?
-
输入
-
有多组测试数据
每组测试数据第一行有两个数n和k,接下来一行有n个数Wi和Vi。
(1<=k=n<=10000) (1<=Wi,Vi<=1000000)
输出
- 输出使得单位价值的最大值。(保留两位小数) 样例输入
-
3 2 2 2 5 3 2 1
样例输出
-
0.75
-
有多组测试数据
//方法是一个二分搜索 + 贪心
#include <stdio.h>
#include <stdlib.h>
#define N 11000
double a[N];
int n,k,i;
struct node
{
double w;
double v;
// 价值差 即为 自己本来的价值 和 物品重量 * 所找的最高单价 之间的差值
}s[N];
int cmp(const void *a,const void *b)
{
return * (double *)a > * (double *)b ? -1 : 1;// 价值差 从大到小 排列
}
int fun2(double x)
{
for(i=0;i<n;i++)
{
a[i]=s[i].v-x*s[i].w; //代表的是 自己本来的价值 - 物品重量*最高单价
}
qsort(a,n,sizeof(double),cmp);
double sum=0;
for(i=0;i<k;i++)
{
sum+=a[i]; //把 所要的选的 最大的价值差 累加
}
return sum>=0 ? 1 : 0; //看价值差 是否大于 0
}
double fun1(double max)
{
double left=0,right=max,mid;
for(int i=0;i<100;i++)
{
mid=(left+right)/2;
if(fun2(mid)) // 满足时说明 所选的最高单价 小于或者等于所要 找的最高单价
left=mid;
else
right=mid;
}
return left;
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
double max=0;
int i;
for(i=0;i<n;i++)
{
scanf("%lf%lf",&s[i].w,&s[i].v);
double cmp=s[i].v/s[i].w;
if(cmp>max) //找到最大的单位价值量
{
max=cmp;
}
}
printf("%.2lf\n",fun1(max));
}
return 0;
}