小W的斜率

题解:很神奇的做法,将平面的上的点按照某一方向排序,方向用斜率表示,显然这个方向是 P/Q的垂直方向,即-Q/P。

怎么排呢?方程①: y=kx+y0-kx0,方程②: y=k'x,方程③:k*k'=-1,方程④:k=P/Q,联立解得:y=(y0-kx0)/(k^2+1),比较的重点就是这里的y了。因为k^2+1>=1,故比较Q*y0-P*x0的大小。

 1 #pragma warning(disable:4996)
 2 #include<string>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 #define ll long long
 8 using namespace std;
 9 
10 const int maxn = 1000005;
11 
12 int n, P, Q;
13 int x[maxn], y[maxn], id[maxn];
14 
15 bool cmp(int i, int j) {
16     return -(double)x[i] * P + (double)y[i] * Q < -(double)x[j] * P + (double)y[j] * Q;
17 }
18 
19 double cal(int i) {
20     double k1 = x[id[i] + 1] == x[id[i]] ? 1e18 : 1.0 * (y[id[i] + 1] - y[id[i]]) / (x[id[i] + 1] - x[id[i]]);
21     double k2 = Q == 0 ? 1e18 : 1.0 * P / Q;
22     return fabs(k1 - k2);
23 }
24 
25 ll gcd(ll a, ll b) {
26     if (!a) return b;
27     if (!b) return a;
28     return a % b ? gcd(b, a%b) : b;
29 }
30 
31 int main()
32 {
33     while (scanf("%d%d%d", &n, &P, &Q) != EOF) {
34         for (int i = 1; i <= n; i++) {
35             scanf("%d%d", &x[i], &y[i]);
36             id[i] = i;
37         }
38         sort(id + 1, id + n + 1, cmp);
39         
40         int p = 1;
41         double m = cal(1);
42         for (int i = 2; i < n; i++) if (cal(i) < m) { m = cal(i); p = i; }
43 
44         ll dy = y[id[p] + 1] - y[id[p]], dx = x[id[p] + 1] - x[id[p]];
45         ll gg = gcd(abs(dy), abs(dx));
46         if (dx < 0 && dy < 0) {
47             dx = -dx;
48             dy = -dy;
49         }
50         printf("%lld/%lld\n", dy / gg, dx / gg);
51     }
52     return 0;
53 }

 

posted @ 2018-05-13 15:49  天之道,利而不害  阅读(210)  评论(0编辑  收藏  举报