前日某硕士同学参加 某公司面试,题目是这样:
如何在一大堆点(坐标x,y已知)中寻找出在一条直线上包含点的个数最大值。编程语言不限。
同学想过各种办法,有些想法很简单,最容易想到的就是遍历,但是实现非常困难。
我的思路:(1)两点之间确定一条直线;
(2)任意一条直线可以用三个参数唯一确定。
形如:y=ax+b;考虑到特殊情况,垂直x轴,增加一个参数v;
当v=1时表示直线与x轴垂直,即两点的横坐标相等;否则为0.
这样一来,任意两个点确定的直线可以用三个参数唯一表示,可以用向量(a,b,v)表示。
如图所示:
C++代码块:
<span style="font-size:18px;">#include <iostream>
using namespace std;
#include <math.h>
#define Error 1e-5
/************************************
**函数名称:MatrixMax(d,M[])*********
**函数功能:返回向量中的元素最大值***
************************************/
int MatrixMax(int d,int Mtr[])
{
for (int i=1;i<d;i++)
if (Mtr[0]<Mtr[i]) Mtr[0]=Mtr[i];
return Mtr[0];
};
/*************************************
**函数名称:SameRowNum(i,N,Mtr[][3])**
**函数功能:返回矩阵行中与第i行相同数*
*************************************/
int SameColNum(int i,int N,double Mt[][3])
{
int sum=0;
for(int j=0;j<N;j++)
if (Mt[i][0]==Mt[j][0]&&Mt[i][1]==Mt[j][1]&&Mt[i][2]==Mt[j][2]) sum++;
return sum;
};
int main()
{
cout << "Please input the number of points:";
int n;//点的个数
cin >> n;
double Point_x[n];//点的横坐标
double Point_y[n];//点的纵坐标
cout<<"Please input the coordinates of points"<<endl;
for (int i=0;i<n;i++)
{
cin >> Point_x[i];
cin >> Point_y[i];
}
int N=n*(n-1)/2;//循环次数
double a[N];//两点确定的直线参数a
double b[N];//两点确定的直线参数b
double v[N];//两点确定的直线参数v
int k=0;
for (int i=0;i<n-1;i++)
for (int j=i+1;j<n;j++)
{
if (Point_x[j]==Point_x[i])
{
a[k]=Point_x[i];
b[k]=0;
v[k]=1;
}
else
{
a[k]=(Point_y[j]-Point_y[i])/(Point_x[j]-Point_x[i]);
b[k]=(Point_x[j]*Point_y[i]-Point_x[i]*Point_y[j])/(Point_x[j]-Point_x[i]);
v[k]=0;
}
k++;
};
/* cout<<"[a;b;v]'="<<endl;
for (int k=0;k<N;k++)
{
cout<<a[k]<<b[k]<<v[k]<<endl;
};*/
double M[N][3];
for (int i=0;i<N;i++)
{
M[i][0]=a[i];
M[i][1]=b[i];
M[i][2]=v[i];
};
int Sum=0;
int K[N];
for (int i=0;i<N;i++)
{
K[i]=SameColNum(i,N,M);
};
Sum=MatrixMax(N,K);
int Max_Point=(1+sqrt(1+8*Sum))/2;
cout<<"在一条直线上最多的点的个数为:"<<Max_Point<<endl;
return 0;
}</span>