Description
塞尔达公主又又又又被抓走了。林克为了找到她需要穿过拉纳鲁沙漠,坏消息是林克可能没有足够的体力穿越沙漠,好消息是沙漠中分布着N个力之果实,坏消息是我们的林克只能走直线。为了穿越沙漠,林克希望能够吃到尽可能多的力之果实。现在请你帮他规划一条直线,使他能够获得尽可能多的力之果实。
Input Format
输入第一行有一个数N,表示沙漠中果实的数量。
接下来的N行每行两个正整数x,y,表示每个力之果实的坐标。
Output Format
输出一个数,表示林克最多能够获得的力之果实的数量。
Sample Input
5
4 4
2 2
9 9
9 11
17 8
Sample Output
3
说明
对于70%的数据,N<=300
对于100%的数据,N<=700
第一种方法: O(n^3)
任取两个点,i j 作为一条直线, 对剩下的所有点中遍历是否在这条直线上. 维护最大值即可,
几点注意的地方:
1.三重循环的起始和结束: 因为i j 和 j i 组成的是同一条直线 所以可以避免重复 . 而k也同样 如果在前面出现过 那么一点计算过 所以不用考虑
或者换一种思路 认为 i是要进行判断的点, j 和 k组成的是直线,所以由刚才的思路 也可以减少循环量.
或者再换一种思路, 认为每个在同一条直线上的所有点组成了给定点集的一个子集, 这个子集至少有两个不重复点, 剩下每次加入一给点都可以认为它是第三个点,所以也要不重复,并且关于三点共线的公式可以直接套用外积公式.
2.能用乘法不要用除法. 这个算是常识吧..好好的整数运算就可以解决的问题搞一个浮点数出来多傻呀..不仅慢 还 占空间.
代码如下:
/* Judging... PROB=1350 LANG=C++ Accepted (Time: 6ms, Memory: 4968kb) Accepted (Time: 6ms, Memory: 4964kb) Accepted (Time: 5ms, Memory: 4956kb) Accepted (Time: 6ms, Memory: 4952kb) Accepted (Time: 8ms, Memory: 4968kb) Accepted (Time: 11ms, Memory: 4956kb) Accepted (Time: 17ms, Memory: 4964kb) Accepted (Time: 140ms, Memory: 4960kb) Accepted (Time: 262ms, Memory: 4968kb) Accepted (Time: 187ms, Memory: 4952kb) */ #include <iostream> using namespace std; int x[701]={0},y[701]={0};//700个点 int main(int argc, char const *argv[]) { int n; cin>>n; for (int i = 0; i < n; ++i) { cin>>x[i]>>y[i]; } //Cn2 枚举两个点 确定一条直线 //然后 枚举每个点 判断三点是否共线 int max = 2; for (int i = 0; i < n-2; ++i) { for (int j = i+1; j < n-1; ++j) { int count = 2; //i 和 j 组成了一条直线 if(x[i]==x[j] and y[i]==y[j]) continue; for (int k = j+1; k < n; ++k) { //研究k点是否在 i j 直线上 bool isOn = ( (y[j]-y[i])*(x[k]-x[i]) == (x[j]-x[i]) *(y[k]-y[i]) ); if(isOn) count++; } if(count > max) max = count; } } cout<<max<<endl; return 0; }