原题链接:原题地址
Description
NBA每年都有球员选秀环节。通常用速度和身高两项数据来衡量一个篮球运动员的基本素质。假如一支球队里速度最慢的球员速度为minV,身高最矮的球员高度为minH,那么这支球队的所有队员都应该满足: A * ( height – minH ) + B * ( speed – minV ) <= C 其中A和B,C为给定的经验值。这个式子很容易理解,如果一个球队的球员速度和身高差距太大,会造成配合的不协调。 请问作为球队管理层的你,在N名选秀球员中,最多能有多少名符合条件的候选球员。
Input
第一行四个数N、A、B、C 下接N行每行两个数描述一个球员的height和speed
Output
最多候选球员数目。
Sample Input
4 1 2 10
5 1
3 2
2 3
2 1
Sample Output
4
HINT
数据范围: N <= 5000 ,height和speed不大于10000。A、B、C在长整型以内。
朴素想法:直接枚举minh和minv再统计符合要求个数,时间复杂度为O(n^3),无法承受。可以换个思路(以下用a和b代替身高和速度):
由题目的不等式A * ( height – minH ) + B * ( speed – minV ) <= C ,移项后为A*height+B*speed<=C+A*minH+B*minV。那么可以以定义c[i]=A*a[i]+B*b[i],枚举到一个mina和minb时,设lim=A*mina+B*minb,则只需统计满足c[i]<=lim的个数。我们以c[i]的值对运动员排序,先枚举mina,再从小到大枚举minb,计算好lim,用一个指针p指向当前扫到的c[i],并且一直右移指针直到c[i]>lim。此时换下一个minb因为b从小到大枚举,显然lim的值不会变小,则指针p也不会回溯。但注意随着minb的值增大,之前计算过的人中可能会有人的b值会小于minb。解决方法很简单,用cnt表示当前mina下找到的队员个数,在计算完当前mina和minb的cnt并且更新了答案之后,如果这个minb对应的队员的c值大于lim,那么cnt–即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 5010
using namespace std;
struct man{
int a,b,c;
}da[maxn],bb[maxn];
bool cmp1(man a,man b){
return a.b<b.b;
}
bool cmp2(man a,man b){
return a.c<b.c;
}
int main(){
freopen("10396.in","r",stdin);
int n,a0,b0,c0;
scanf("%d%d%d%d",&n,&a0,&b0,&c0);
for(int i=1;i<=n;i++){
scanf("%d%d",&da[i].a,&da[i].b);
da[i].c=a0*da[i].a+b0*da[i].b;
bb[i]=da[i];
}
sort(da+1,da+n+1,cmp2);
sort(bb+1,bb+n+1,cmp1);
int ans=0;
for(int i=1;i<=n;i++){
int p=1,cnt=0;
for(int j=1;j<=n;j++)if(da[i].a<=bb[j].a&&bb[j].b<=da[i].b){
int lim=a0*da[i].a+b0*bb[j].b+c0;
while(p<=n&&da[p].c<=lim){
if(da[p].a>=da[i].a&&da[p].b>=bb[j].b)cnt++;
p++;
}
ans=max(cnt,ans);
if(bb[j].c<=lim)cnt--;
}
}
printf("%d\n",ans);
return 0;
}