1. 程式人生 > 實用技巧 >C - Line-line Intersection

C - Line-line Intersection

題目連結:https://vjudge.net/problem/Gym-102220C

一般式是真的好用.jpg

題目大意:給你一條直線的兩個點 問這些直線可以找幾組兩兩相交的(比如三條線交於一點 算三組) 如果兩直線重合 算有交點

剛看這題的時候有個學長說 這題卡精度卡的要死...於是就沒敢做除法運算

總體思路是 設直線為ax+by+c=0

兩直線如果平行 則a/b相等 即兩條直線的(a,b)向量相等(讓a大於0)

如果(a,b,c)也相等 則說明兩直線重合

也就是說 先把所有平行及重合的拋去 然後再加上重合的組數 就是最後結果

程式碼如下:(學長的程式碼)

#include<bits/stdc++.h>
#define
ll long long #define inf 0x3f3f3f3f #define ms(x,a) memset(x,a,sizeof(x)) #define vc vector #define pb(x) push_back(x) #define debug cout<<"***"<<endl #define sd(x) scanf("%d",&x) #define sdd(x,y) scanf("%d%d",&x,&y) #define sl(x) scanf("%lld",&x) #define sll(x,y) scanf("%lld%lld",&x,&y) #define
pd(x) printf("%d\n",x) #define pl(x) printf("%lld\n",x) #define rep(i,a,b) for(int i = a;i <= b;i++) using namespace std; const int maxn = 2e5 + 10; const ll mod = 1e9 + 7; int n,m; ll a[maxn]; pair<ll,ll>p1,p2; pair<pair<ll,ll>,pair<ll,ll> >p3; map<pair<ll,ll>,ll>mp1; map
<pair<pair<ll,ll>,pair<ll,ll> >,ll>mp2; ll gcd(ll a,ll b){ return b == 0 ? a : gcd(b,a % b); } int main() { int t; scanf("%d",&t); for(int ca = 1;ca <= t;ca++){ mp1.clear(); mp2.clear(); sd(n); rep(i,1,n){ ll x1,x2,y1,y2; sll(x1,y1),sll(x2,y2); ll a = y1 - y2,b = x2 - x1,c = x1 * y2 - x2 * y1; ll d1 = gcd(a,b),d2 = gcd(b,c); p1 = make_pair(a / d1,b / d1); p2 = make_pair(b / d1,c / d1); p3 = make_pair(p1,p2); mp1[p1]++; mp2[p3]++; } ll ans = (ll)n * (n - 1) / 2; for(auto x : mp1){ ll tmp = x.second; ans -= tmp * (tmp - 1) / 2; } for(auto x : mp2){ ll tmp = x.second; ans += tmp * (tmp - 1) / 2; } cout<<ans<<endl; } return 0; }