题目描述
一天,小明坐在院子里数星星,Gardon就出了个难题给他,让他数数天上的星星最多有多少个是在同一条直线上的。天上的星星太多了,小明马上就看花了眼,你能写个程序来帮他计算么?
输入
首先输入一个整数N(N<=300),接下来的N对数每对表示一个星星的位置(星星的坐标在-10000到10000之间,精确到小数点后1位)。没有两个星星会在同一个位置。
输出
一个整数,表示一条直线上最多星星的数目。
样例输入
5
0 0
1 0
1 1
0 1
0.5 0.5
样例输出
3
分析与解
我以维特根斯坦的论述方式来分析:
对于斜率,点,以及线段来说:
1.两点确定一条直线,直线具有斜率
2.斜率可以取0到无穷
3.斜率为无穷时说明直线与y轴平行或重合
4.斜率为无穷时说明斜率公式中分母为零
5.斜率为无穷时,其值具有相对性:2−00−0和−1−00−0\frac{2-0}{0-0}和\frac{-1-0}{0-0}0−02−0和0−0−1−0
一个是正无穷,一个是负无穷,但是其都是在一条直线上的(y轴)。
6.共线问题建立在三个点的基础之上
7.我们不能通过一般的斜率公式是否相等来断定三个点是否共线
8.可以通过乘式判断3点共线
(y3−y1)(x2−x1)−(y2−y1)(x3−x1)=0(y3−y1)(x2−x1)−(y2−y1)(x3−x1)=0(y3−y1)(x2−x1)−(y2−y1)(x3−x1)=0
9.n个点,每一个点都能和剩下n-1个点组成线段
10.当每个点都不共线时,n个点组成的不同直线的个数最多
11.A点和B点组成线段也意味着B点和A点组成线段
12.n个点组成最多不同直线个数为n∗(n−1)2\frac {n*(n-1)}{2}2n∗(n−1)
解题思路:
1.确定两个点,找第三个点,看看他们是否共线,如果共线,当前标记数组加一。
2.两个确定点要取到所有不重复情况。
3.两个点,那么一定共线,所以我们只需要找有多少其余的点在那条线上。然后再加上2就是所有在这条线上的点。
代码
#include<iostream>
#include<algorithm>
using namespace std;
struct star{double x;double y;
};
int main(){int n;star s[333];cin>>n;for(int i=0;i<n;++i){cin>>s[i].x>>s[i].y;}int m=0;int b[100860];for(int i=0;i<n;++i){for(int j=i+1;j<n;++j){for(int k=j+1;k<n;++k){if((s[k].y-s[i].y)*(s[k].x-s[j].x)-(s[k].y-s[j].y)*(s[k].x-s[i].x)==0){b[m]+=1;}}m++;}}sort(b,b+m);if(n==1) cout<<1;else if(n<=0) cout<<0;else cout<<b[m-1]+2;
}