话说,有N个点,求共线最大点数,我们可以这么求,点两两构成直线,假设点p1与p2构成直线和p2与p3构成直线一模一样,那么就可以判断p1,p2,p3共线了;再举个例子,假设N个点中,共线的最多点数为m个,那么这m个点组成的直线一定是相同的,所以如果我们求出来了这m个点构成的直线数,那么就可以反求得点数m。基于此,我们定义直线类型,直线类型应该有斜率k,x轴截距,y轴截距,直线数四个参数构成。
叽里咕噜说了一大堆,
#include <stdio.h>
#include<math.h>
///点结构体
typedef struct
{
double x;
double y;
} Point;
///直线结构体,每一个直线由三个参数决定,分别是斜率、x轴截距、y轴截距,必须是三个参数
typedef struct
{
double x_axis;
double y_axis;
double k;
int count;
} Line;
int m=0;
void fun(Line line[],Point point[],int n)
{
int i,j,t;
double k,b,x_axis,y_axis;//分别表示直线的斜率,截距,x轴截距,y轴截距
for(i=0; i<n-1; i++)
{
for(j=i+1; j<n; j++)
{
///三个条件语句分别处理垂直于x轴直线,垂直于y轴直线,普通直线
if(fabs(point[i].x-point[j].x)<1e-5)
{
k=1e5;
x_axis=point[i].x;
y_axis=1e5;
}
else
{
if(fabs(point[i].y-point[j].y)<1e-5)
{
k=0;
x_axis=1e5;
y_axis=point[i].y;
}
else
{
k=(point[i].y-point[j].y)/(point[i].x-point[j].x);
b=-1.0*k*point[i].x+point[i].y;
x_axis=-1*b/k;
y_axis=b;
}
}
for(t=0; t<m; t++)//在已产生的直线中找找看该直线是否已存在
{
if((fabs(line[t].x_axis-x_axis)<1e-5)&&(fabs(line[t].y_axis-y_axis)<1e-5)&&(fabs(line[t].k-k)<1e-5))
{
line[t].count++;
break;
}
}
if(t==m)//说明是新直线
{
line[m].x_axis=x_axis;
line[m].y_axis=y_axis;
line[m].k=k;
line[m].count=1;
m++;
}
}
}
}
int main()
{
Line line[100];
Point point[100];
int n;
///从文件中读入点坐标
FILE *fp=fopen("data.txt","r+");
fscanf(fp,"%d",&n);
int i;
for(i=0; i<n; i++)
{
fscanf(fp,"%lf %lf",&point[i].x,&point[i].y);
printf("%lf %lf\n",point[i].x,point[i].y);
}
fun(line,point,n);
printf("\n---------------------------结果------------------------------:\n\n");
int j=0;//寻找点数的参数
int max=0;
for(i=0; i<m; i++)
{
for(j=1; (j*(j-1)/2!=line[i].count)&&(j<line[i].count); j++);///根据直线数点数j与边数目满足,边数=j*(j-1)/2
printf("在以斜率为%lf,x轴截距为%lf,y轴截距为%lf的直线上点数有:%d个 \n\n",line[i].k,line[i].x_axis,line[i].y_axis,j);
if(max<=j)
{
max=j;
}
printf("所以共线最多的点数为%d个\n",max);
}
}
文件中坐标点数据(第一个数为点个数):
7
0 0
1 1
2 2
3 3
1 2
3 2
3 0
第一次写东西,不容易呐!