这道题难应该就难在题目理解上吧,这个题大致意思就是给你n条直线,每条直线由两个点确定,然后Alice从中选择1~n条直线,然后Bob在n条直线中选择一条直线,输出Alice选的直线与Bob选择的直线的交点最少。
因为Alice想要选择尽可能多的直线与Bob选择的直线相交,所以Alice尽可能选择不平行的直线,Bob想要选择一条直线与尽可能少的直线相交,所以选择与更多平行的直线平行的那一条直线。
我们用pair来记录dx和dy,用最大公倍数进行化简。
完整代码如下:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn = 1e5 + 10;
typedef pair<int,int>P;
P point[maxn];
int ans[maxn];
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main(){
int t;
cin >> t;
while(t--){
int n;
cin >> n;
for(int i=1;i<=n;i++){
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int dx = x2 - x1;
int dy = y2 - y1;
if(dx == 0) dy = 1;//一条竖线
else if(dy == 0) dx = 1;//一条横线
else{
if(dx < 0) dx = -dx, dy = -dy;
int x = gcd(abs(dx),abs(dy));
dx /= x;
dy /= x;
}
point[i] = P(dx,dy);
}
sort(point+1,point+n+1);
for(int i=1;i<=n;i++) ans[i] = 0;
int j;
for(int i=1;i<=n;i = j){//统计平行线
for(j=i;j<=n && point[i] == point[j];j++);
for(int k=1;k<=j-i;k++) ans[k]++;
}
int i;
for(i=j=1;i<=n;i++){
while(!ans[j]) j++;
ans[j]--;
printf("%d\n",i - j);
}
}
return 0;
}