11.02T1 几何

倾斜的线

(slope.cpp)

【问题描述】

给定两个正整数PQ。在二维平面上有n个整点。现在请你找到一对点使得经过它们的直线的斜率在数值上最接近P/Q(即这条直线的斜率与P/Q的差最小),请输出经过它们直线的斜率p/q。如果有两组点的斜率的接近程度相同,请输出较小的斜率。保证答案的p/q> 0,即输出的pq都是正整数。

【输入格式】

输入文件名为slope.in

第一行三个正整数n P Q

接下来n行每行两个正整数x y表示一个点的坐标。保证不存在x坐标相同或者y坐标相同的点(即斜率不会为无穷大与0)。

【输出格式】

输出文件名为slope.out

输出仅一行,格式为p/q,表示最接近的斜率,其中pq都是正整数。

【样例输入与输出】

example_slope1.in

example_slope1.out

6 15698 17433

112412868 636515040

122123982 526131695

58758943 343718480

447544052 640491230

162809501 315494932

870543506 895723090

193409386/235911335

       更多样例请见example/slope/目录。

【数据范围】

对于1~10号测试点(50%):n<=1000。

对于所有测试点(100%):n<=400000。

 

 

 

 

把所有点按照P/Q斜率投射到y轴上排序,可以证明相邻的点对应的线段一定有一条是最优解,因为不相邻的点与给定的斜率夹角比相邻的大

code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define N 1000006 
 6 using namespace std;
 7 struct node{
 8     long double x,y,w;
 9 }e[N];
10 bool cmp(const node&a,const node&b){
11     return a.w<b.w;
12 }
13 long double getk(int i,int j){
14     return (e[i].y-e[j].y)/(e[i].x-e[j].x);
15 }
16 int gcd(int a,int b){
17     if(a<b)swap(a,b);
18     while(a=a%b)swap(a,b);
19     return b;
20 }
21 int main(){
22     int n;
23     long double P,Q;
24     cin>>n>>P>>Q;
25     for(int i=1;i<=n;i++){
26         cin>>e[i].x>>e[i].y;
27         e[i].w=e[i].y-e[i].x*P/Q;
28     }
29     sort(e+1,e+n+1,cmp);
30     long double delta=9999999.0;
31     int now1,now2;
32     for(int i=1;i<n;i++){
33         if(fabs(getk(i,i+1)-P/Q)<delta){
34             now1=i,now2=i+1;
35             delta=fabs(getk(i,i+1)-P/Q);
36         }
37         else if(fabs(getk(i,i+1)-P/Q)==delta){
38             if(getk(i,i+1)-P/Q<0){
39                 now1=i,now2=i+1;
40             }
41         }
42     }
43     int deltax=e[now1].x-e[now2].x,deltay=e[now1].y-e[now2].y;
44     if(deltax<0)deltax=-deltax,deltay=-deltay;
45     int GCD=gcd(abs(deltax),abs(deltay));
46     cout<<deltay/GCD<<"/"<<deltax/GCD;
47     return 0;
48 }

over

posted @ 2018-11-02 21:15  saionjisekai  阅读(218)  评论(0编辑  收藏  举报