Power Transmission (Hard Edition)(几何)

题目链接: 

https://codeforces.com/problemset/problem/1163/C2

题目大意:

有n个点,然后这些点直线都可以互相连线,然后问你有多少对直线是相交的。

题解:https://codeforces.com/blog/entry/66943

具体思路:

首先,我们可以将直线转换成这种形式 a*x - b*y = c.然后当前的点是(x1,y1)和(x2,y2)。我们此时的系数分别是 a = ( y2 - y1 ) , b = ( x2 - x1 ) , c= (x1 * y2 - x2 *y1).

注意化式子的时候为了保证正确性,我们可以使得a的系数都是正的,然后如果a的系数是0的话,我们再保证b是正的,这样会避免成比例成相反数的情况。

注意去重的时候,如果两个式子的表达式完全一样,那么这个式子应该只算一个。如果已经存在当前斜率相同的,但是为平行关系,我们这个时候应该计算总的合法边数 - 和当前边斜率相等边数。

AC代码:

 1 #include<iostream>
 2 #include<map>
 3 #include<string>
 4 #include<cstring>
 5 #include<bits/stdc++.h>
 6 using namespace std;
 7 # define inf 0x3f3f3f3f
 8 # define ll long long
 9 const ll mod = 998244353;
10 const int maxn = 2e3+100;
11 struct node
12 {
13     int x,y;
14 } q[maxn];
15 struct Line
16 {
17     int a,b,c;
18     Line() {}
19     Line(int xx,int yy,int zz)
20     {
21         a=xx,b=yy,c=zz;
22     }
23 } line[maxn];
24 //map<pair<int,int>,int>cnt;
25 //map<pair<int,int>,bool>repat;
26 map<pair<int,int>,set<int> >vis;
27 int main()
28 {
29     int n;
30     scanf("%d",&n);
31     for(int i=1; i<=n; i++){
32         scanf("%d %d",&q[i].x,&q[i].y);
33     }
34     ll ans=0,tot=0;
35     for(int i=1; i<=n; i++)
36     {
37         for(int j=i+1; j<=n; j++)
38         {
39             int t1 = q[j].y-q[i].y;
40             int t2 = q[j].x-q[i].x;
41             int t3 = q[i].x*q[j].y-q[j].x*q[i].y;
42             int tmp=__gcd(t1,t2);
43             t1/=tmp,t2/=tmp;
44             if(t1<0||(t1==0&&t2<0))// 注意系数
45                 t1=-t1,t2=-t2;
46             tmp=t2*q[i].y-t1*q[i].x;
47             if(vis[make_pair(t1,t2)].count(tmp)==0)
48             {
49                 tot++;
50                 vis[make_pair(t1,t2)].insert(tmp);
51                 ans+=tot-vis[make_pair(t1,t2)].size();
52             }
53         }
54     }
55     printf("%lld\n",ans);
56     return 0;
57 }

 

    

 

 

posted @ 2019-05-23 22:12  Let_Life_Stop  阅读(334)  评论(0编辑  收藏  举报