2021杭电多校
2021“MINIEYE杯”中国大学生算法设计超级联赛(3)1004 Game on Plane
题目大意
给定 n n n 条直线 给定两个点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1) ( x 2 , y 2 ) (x_2,y_2) (x2,y2) 描述 ,输出 n n n 行第 i i i 行表示在 n n n 条直线选取 i i i 根直线使这些直线与画的线交点个数尽量的多 任意画一条直线与选取的各直线的总交点个数(重合也算1个交点)输出其与选取的直线的最小交点个数
题解
对于选取直线:为使交点个数尽量多 需要选尽量多不同斜率的直线
对于画的直线:其斜率与选取相同斜率直线数量最多的直线相同 其交点个数为选取的直线 - 最多相同斜率的直线数量
代码
#include<bits/stdc++.h>
using namespace std;
int t,n,xa,ya,xb,yb,dx,dy,i,j,k;
int f[100003];
pair<int,int> a[100003];
int gcd(int a,int b)
{
if(b==0)return a;
else gcd(b,a%b);
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%d%d%d%d",&xa,&ya,&xb,&yb);
dx=xa-xb;
dy=ya-yb;
if(dx==0)dy=1;
else if(dy==0)dx=1;
else
{
if(dx<0)
{
dx=-dx;
dy=-dy;
}
int d=gcd(fabs(dx),fabs(dy));
dx/=d;
dy/=d;
}
a[i].first=dx;
a[i].second=dy;
}
sort(a+1,a+n+1);
for(int i=1;i<=n;++i)f[i]=0;//初始化记录斜率相同数量的组数
for(int i=1;i<=n;i=j)
{
for(j=i;j<=n&&a[i]==a[j];++j);//j-i描述斜率相同直线数量
for(int k=1;k<=j-i;++k)f[k]++;
}
for(int i=1,j=1;i<=n;++i)
{
while(f[j]==0)++j;
--f[j];//--意味该线被选取
printf("%d\n",i-j);//j来描述当前相同斜率最多的条数
}
}
return 0;
}