zoukankan      html  css  js  c++  java
  • 多校 #5 hdu 5784 How Many Triangles

    http://acm.hdu.edu.cn/showproblem.php?pid=5784

    给定平面上互不相同的n个点,求所有锐角三角形的个数。3<=n<=2000

    锐角三角形因为要三个角都是锐角,所以限制条件多。即使枚举一个点,另外两条边用极角排序,也只能维护一个锐角,剩下的两个角难于统计。

    但是,如果换一种思路,统计所有直角、钝角以及三点共线的个数 ,问题就简单多了。因为因为只有一个直角或钝角或平角,只需依次对每个点,统计以它为哪一个特殊角的直角、钝角、平角三角形有多少即可。

    具体做法是对点i,把所有其它点按极角排序。为保证每个不合法三角形(包括平角三角形)只被统计一次,直角、钝角三角形只在一条边时统计(以i为顶点的两条边,分别逆时针旋转直到碰到另一条边,转的角度小的那一条边。)所以维护k为从边 i-j 以 i 为顶点逆时针旋转小于等于180度的最后一个点,l 为边 i-j 逆时针旋转小于90度的最后一个点。这样l到k之间就都是不合法三角形了。因为k,i,j构成的可以使平角,为了避免平角被算两次,可以强制规定在两种中取某一种计算。

    为了操作简便,我是把除了i的n-1个点极角排序后,又在后面复制了一遍,不过角度都加了360度。

    这种题如果用double计算可能会出现精度问题,我选择除了极角排序用double外,所有角度的判断均使用long long的点积和叉积判断,绝对不会出现精度问题。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <string>
      4 #include <cstring>
      5 #include <algorithm>
      6 #include <cmath>
      7 using namespace std;
      8 
      9 const double pi = acos(-1.0);
     10 
     11 struct point {
     12     long long x,y;
     13     point() {}
     14     point(long long xx, long long yy) {
     15         x = xx, y = yy;
     16     }
     17     point operator -(const point &p) const {
     18         return point(x - p.x, y - p.y);
     19     }
     20 }a[2010];
     21 struct sta {
     22     double theta; int id;
     23     sta() {}
     24     sta(double thetaa,int idd) {
     25         theta = thetaa, id = idd;
     26     }
     27     bool operator <(const sta &p2) const {
     28         return theta<p2.theta;
     29     }
     30 }b[4010];
     31 
     32 long long dot(const point &p1, const point &p2)
     33 {
     34     return p1.x*p2.x + p1.y*p2.y;
     35 }
     36 long long det(const point &p1, const point &p2)
     37 {
     38     return p1.x*p2.y - p1.y*p2.x;
     39 }
     40 
     41 int main()
     42 {
     43     int i,j,k,l;
     44     long long ans,cnt,n;
     45     while(cin >> n)
     46     {
     47         
     48         for(i = 1; i<=n; i++)
     49             cin >> a[i].x >> a[i].y;
     50             
     51         ans = (long long)n*(n-1)*(n-2)/6;
     52         
     53         for(i = 1; i<=n; i++)
     54         {
     55             int tot = 0;
     56             cnt = 0;
     57             for(j = 1; j<=n; j++)
     58                 if(j!=i) {
     59                     double theta;
     60                     if(a[j].x==a[i].x)
     61                         theta = (a[j].y>a[i].y? pi*0.5 : pi*1.5);
     62                     else {
     63                         theta = atan2(a[j].y-a[i].y, a[j].x-a[i].x);
     64                         if(theta<0) theta += 2.0*pi;
     65                     }
     66                     b[++tot] = sta(theta, j);
     67                 }
     68             sort(b+1, b+n);
     69             for(j = n; j<=2*n-2; j++)
     70             {
     71                 b[j] = b[j-n+1];
     72                 b[j].theta += 2.0*pi;
     73             }
     74 
     75             long long temp;
     76             for(k = l = j = 1; j<n; j++) {
     77                 
     78                 if(det(a[b[j].id] - a[i], a[b[k].id] - a[i])==0ll
     79                     && dot(a[b[j].id] - a[i], a[b[k].id] - a[i])<0ll
     80                     && k>=n) temp = temp;
     81                 else temp = 0;
     82                 while(b[k+1].theta-b[j].theta < pi+1.0
     83                   && det(a[b[j].id] - a[i], a[b[k+1].id] - a[i])>=0ll) {
     84                     k++;
     85                     if(det(a[b[j].id] - a[i], a[b[k].id] - a[i])==0ll
     86                     && dot(a[b[j].id] - a[i], a[b[k].id] - a[i])<0ll
     87                     && k>=n)
     88                         temp++;
     89                     else temp = 0;
     90                 }
     91                 while(b[l+1].theta-b[j].theta<pi
     92                   && dot(a[b[j].id] - a[i], a[b[l+1].id] - a[i])>0) l++;
     93                 cnt += k-l;
     94                 cnt -= temp;
     95             }
     96             ans -= cnt;
     97         }
     98         cout << ans << endl;
     99     }
    100     return 0;
    101 }
    View Code
  • 相关阅读:
    open stack总结
    Nginx操作命令
    Nginx 配置详解
    Linux 常用命令-- top
    CEPH 使用SSD日志盘+SATA数据盘, 随OSD数目递增对性能影响的递增测试
    MyCat水平分库
    MyCat垂直分库
    MyCat基本知识
    utf8mb4复杂昵称问题
    Power安装linux-BIG ENDIAN mysql编译安装
  • 原文地址:https://www.cnblogs.com/liuaohan/p/5730310.html
Copyright © 2011-2022 走看看