以二分算法枚举答案的方法非常高效,枚举所需的时间复杂度只需O(logN)
设x为答案,check(x)只有真假两种取值。
能够使用二分枚举算法的条件:
存在一个X,当x小于X时和x大于X时,check(x)真假值不一样。
二分枚举即能够找出真假之间的边界,这个就是所求在满足题意下的最值了。
如果x是浮点数,那么边界的取值注意精度即可。
const double eps=1e-7;
while(l+eps<r)
{ mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid;
}
如果x是整数,那么注意所求,是真值区的最大值还是最小值,见例题。
例题:https://www.nowcoder.com/acm/contest/52/E
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
int c[10005],v[10005];
long long p[10005];
int n,k;
bool check(int x)
{ for(int i=0;i<n;i++)
p[i]=v[i]-x*c[i];
sort(p,p+n);
long long sum=0;
for(int i=n-1;i>=n-k;i--)
sum+=p[i];
return sum>=0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
scanf("%d%d",&c[i],&v[i]);
int l=0,r=100000,mid,res;
while(l<=r)
{ mid=(l+r)/2;
if(check(mid))
{ res=mid;
l=mid+1;
}
else r=mid-1;
}
printf("%d\n",res);
}
return 0;
}