1. 程式人生 > 其它 >AtCoder Beginner Contest 248 E - K-colinear Line // 計算幾何

AtCoder Beginner Contest 248 E - K-colinear Line // 計算幾何

原題連結:E - K-colinear Line (atcoder.jp)

 

題意:

給出直角座標系上N個點(N <= 300),求經過這些點中至少K個點的直線數量,若有無窮多條,則輸出"Infinity"。

 

思路:

  • 兩點確定一條直線:

    當K=1時,答案自然是無窮多條。

    當K >= 2時,我們可以列舉兩點,求出其確定的直線,再列舉所有點,判斷該直線經過的點數是否不少於K。

  • 求直線方程:用直線的一般式方程Ax+By+C=0(普適性)來表示直線。

    已知經過點(x1,y1),(x2,y2),那麼A = y2 - y1, B = x1 - x2, C = x2 * y1 - x1 * y2。

    為了方便直線的判重,對引數進行處理(唯一性),使得:ABC三數公因數為1,A > 0 或 A = 0 且 B > 0。

 

程式碼參考:

//Jakon:計算幾何
#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 310;

int n, k, x[N], y[N];
set<array<int,3>> S;

int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a % b);
}

signed main()
{
    cin 
>> n >> k; for(int i = 1; i <= n; i++) cin >> x[i] >> y[i]; if(k == 1) { cout << "Infinity" << endl; return 0; } for(int i = 1; i <= n; i++) { for(int j = i + 1; j <= n; j++) { // A = y2 - y1, B = x1 - x2, C = x2 * y1 - x1 * y2
int A = y[j] - y[i], B = x[i] - x[j]; int C = x[j] * y[i] - x[i] * y[j]; int g = gcd(gcd(A, B), C); A /= g, B /= g, C /= g; if(A < 0 || A == 0 && B < 0) { A = -A, B = -B, C = -C; } int cnt = 0; for(int k = 1; k <= n; k++) { if(A * x[k] + B * y[k] + C == 0) ++ cnt; } if(cnt >= k) S.insert({A, B, C}); } } cout << S.size() << endl; return 0; }