和疯牛问题有点像,也是用二分+贪心,二分不仅可以排序,还可以用来快速查找数,
#include "iostream"
using namespace std;
#include "algorithm"
const int N=11000;
int w[N],v[N];//w重量,v价值
double remain[N];//存放剩余价值
int n,k;
double max1=-9999;
bool check(double mid)
{
for(int i=0;i<n;i++)
{
remain[i]=v[i]-mid*w[i]; /*此时尝试总单位价值为mid时
每个物品的剩余的价值*/
}
sort(remain,remain+n);/*将剩余价值小到大排序*/
double sum=0;
for(int i=0;i<k;i++)/*选择k个物品*/
{
sum+=remain[n-i-1];/*将剩余价值最大的k个的价值相加*/
}
if(sum>=0)/*此时说明mid不是最优的,因为k个物品中还有剩余的价值,浪费了*/
return 1;
else
return 0;/*k个物品的价值被压榨完了,此时mid可以,返回0,增大mid再试试*/
}
void Search()
{
/*二分搜索,找出最合适的价值,这个价值一定大于0,小于我们
刚才求出的每个的单位最大价值*/
double low,high,mid;
low=0;
high=max1;
for(int i=0;i<100;i++)/*结果保留两位小数*/
{
mid=(low+high)/2;
if(check(mid))
low=mid;/*返回1说明尝试的价值mid满足,但还有机会增大*/
else
high=mid;/*返回0说明尝试的价值mid有点大了,我们进行缩小,继续尝试*/
}
cout<<low<<endl;
}
int main()
{
while(cin>>n>>k)
{
for(int i=0;i<n;i++)
{
cin>>w[i]>>v[i];
if(max1<(v[i]/w[i])) /*找到每个单位最大价值*/
max1=v[i]/w[i];
}
Search();
}
return 0;
}