小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 }