01分数规划
01分数规划问题是求性价比问题,比如说给出总价值和总花费让你求其二者比值的最大值
假设价值为(a[i]),花费为(b[i]),求:
[frac{sum a[i]}{sum b[i]}=ans
]
求其(ans)的最大值。
我们移项发现:
[F(ans)=sum a[i]-ans*sum b[i]
]
变化:
[F(ans)=sum (a[i]-ans*b[i])
]
我们可以从上述公式知道如果是最大价值时(F(ans)=0),当(F(ans)>0)时说明我们二分的答案过小,所以缩小左边界,然后继续二分答案,知道(F(ans)=0)
链接:https://ac.nowcoder.com/acm/problem/14662
来源:牛客网
题目描述
小咪是一个土豪手办狂魔,这次他去了一家店,发现了好多好多(n个)手办,但他是一个很怪的人,每次只想买k个手办,而且他要让他花的每一分钱都物超所值,即:买下来的东西的总价值/总花费=max。请你来看看,他会买哪些东西吧。
输入描述:
多组数据。
第一行一个整数T,为数据组数。
接下来有T组数据。
对于每组数据,第一行两个正整数n,k,如题。
接下来n行,每行有两个正整数ci,vi。分别为手办的花费和它对于小咪的价值。
输出描述:
对于每组数据,输出一个数,即能得到的总价值/总花费的最大值。精确至整数。
思路
求ans最大值:
[frac{总价值}{总花费}=ans
]
显然是01分数规划问题,对于01分数规划我们假设价值是(a[]),花费是(b[]),然后二分答案
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define DOF 0x7f7f7f7f
#define endl '
'
#define mem(a,b) memset(a,b,sizeof(a))
#define debug(case,x); cout<<case<<" : "<<x<<endl;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef long long ll;
using namespace std;
const int maxn = 1e5 + 10;
const double eps=1e-7;
ll a[maxn],b[maxn],c[maxn];
ll n,k;
bool check(ll x){
for(ll i=1;i<=n;++i){
c[i]=a[i]-x*b[i];
}
sort(c+1,c+1+n,greater<ll>());
ll sum=0;
for(ll i=1;i<=k;++i){
sum+=c[i];
}
return sum>=0;
}
int main()
{
ll t;cin>>t;
while(t--){
cin>>n>>k;
for(ll i=1;i<=n;++i)cin>>b[i]>>a[i];
ll l=0,r=1e9,mid;
while(l<=r){
mid=l+r>>1;
if(check(mid))l=mid+1;
else r=mid-1;
}
cout<<r<<endl;
}
}