• Codeforces: Empty Triangle


      这是codeforces gym中的2011-2012 Stanford Local Contest, 8 October, 2011的一道几何题。题意很简单,就是给出500条直线,问你有多少个不被其他直线穿过的三角形。这道题一个很简单的思路就是先要找出每条直线上的交点,因为如果图形是空三角形,那么组成三角形的的每两个顶点都是某条直线上相邻的两个交点。于是我们利用直线的标号,用某条直线上所有点相邻的两条直线与该直线组成三角形,很容易可以找到最多不超过250000个三角形。其中必然会有重复的三角形。如果三角形重复次数是3(最多也只能是3),那么这个就是一个空三角形。用multiset可以很方便的统计重复次数,或者用hash统计也可以。不过现在想到,好像直接make完pair以后排个序直接统计就好了。。囧!

      题目如下:

    Empty Triangles

    Problem Description

    Do you know how easy it is to make a very simple problem into a brutally hard one? Here is an example. How many triangles can you make with N straight lines in the plane? As long as they have different slopes and no three of them meet at a single point, there will be triangles, which is the maximum possible you can get.
    Okay, that wasn't too bad. But let's see what happens if we only count triangles that are empty (that is, none of the lines pass through the interior of the triangle). Then, the number of triangles suddenly becomes very small. For example, with 4 straight lines, we can only make 2 empty triangles, whereas the total number of triangles can be as big as 4. Refer to the diagram.
    In fact, a general formula for the maximum number of empty triangles that can be drawn with N lines is not known. The hard part, however, is to find the right configuration of the lines. Your job is much easier; given N straight lines on the plane, count the number of empty triangles.

    Input

    The input consists of multiple test cases. Each test case begins with a line containing an integer N, 1 ≤ N ≤ 500, which indicates the number of lines on the plane. The next N lines each contain four integers x1, y1, x2, and y2 (between -1000 and 1000), representing a straight line that goes through (x1, y1) and (x2, y2). It is guaranteed that no three lines meet at the same point, and all the lines are distinct.  The input terminates with a line with N = 0.

    Output

    For each test case, print out a single line that contains the number of empty triangles formed by the given lines.

    Sample Input

    4 
    0 0 1 2 
    0 0 -1 2 
    1 0 1 1 
    -1 0 -1 -1 
    5 
    0 0 1 0 
    0 1 1 1 
    0 2 1 2 
    0 3 1 3 
    0 4 1 4 
    0

    Sample Output

    2
    0

    这是3400ms+通过的代码:
    View Code
      1 #include <cstdio>
      2 #include <cmath>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <set>
      6 #include <cassert>
      7 #include <vector>
      8 
      9 #define feq(a, b) (fabs((a) - (b)) < eps)
     10 
     11 using namespace std;
     12 
     13 typedef pair<int, int> pii;
     14 typedef pair<pii, int> piii;
     15 typedef vector<double> vdb;
     16 typedef vector<int> vi;
     17 
     18 const int maxn = 505;
     19 const double eps = 1e-6;
     20 const int mod = 1000007;
     21 
     22 int hash[mod][3], cnt[mod];
     23 //multiset<piii> cnt;
     24 
     25 bool judge(int *a, int *b){
     26     for (int i = 0; i < 3; i++){
     27         if (a[i] != b[i]) return true;
     28     }
     29     return false;
     30 }
     31 
     32 bool insert(int *a){
     33     int p = ((a[0] << 16) + (a[1] << 8) + a[2]) % mod;
     34 
     35     if (p < 0){
     36         p += mod;
     37     }
     38     while (judge(hash[p], a) && cnt[p]) p = (p + 1) % mod;
     39     for (int i = 0; i < 3; i++){
     40         hash[p][i] = a[i];
     41     }
     42     cnt[p]++;
     43     if (cnt[p] == 3) return true;
     44     return false;
     45 }
     46 
     47 struct point{
     48     int id;
     49     double x, y;
     50     bool operator < (const point &a) const{
     51         if (feq(x, a.x)) return y < a.y;
     52         return x < a.x;
     53     }
     54 };
     55 
     56 struct Line{
     57     point a, b;
     58     vector<point> cross;
     59     void fix(){
     60         sort(&cross[0], &cross[0] + cross.size());
     61     }
     62 }line[maxn];
     63 
     64 bool parallel(Line u, Line v){
     65     return feq((u.a.x - u.b.x) * (v.a.y - v.b.y), (v.a.x - v.b.x) * (u.a.y - u.b.y));
     66 }
     67 
     68 point ll_inst(Line l1, Line l2){
     69     point ans = l1.a;
     70     double t = ((l1.a.x - l2.a.x) * (l2.a.y - l2.b.y) - (l1.a.y - l2.a.y) * (l2.a.x - l2.b.x))
     71     / ((l1.a.x - l1.b.x) * (l2.a.y - l2.b.y) - (l1.a.y - l1.b.y) * (l2.a.x - l2.b.x));
     72 
     73     ans.x += (l1.b.x - l1.a.x) * t;
     74     ans.y += (l1.b.y - l1.a.y) * t;
     75 
     76     return ans;
     77 }
     78 
     79 int id[3];
     80 
     81 int main(){
     82     int n;
     83     point tmp;
     84 
     85     while (~scanf("%d", &n) && n){
     86         //cnt.clear();
     87         memset(cnt, 0, sizeof(cnt));
     88         for (int i = 0; i < n; i++){
     89             line[i].cross.clear();
     90             scanf("%lf%lf%lf%lf", &line[i].a.x, &line[i].a.y, &line[i].b.x, &line[i].b.y);
     91             for (int j = 0; j < i; j++){
     92                 if (parallel(line[i], line[j])) continue;
     93                 tmp = ll_inst(line[i], line[j]);
     94                 tmp.id = j;
     95                 line[i].cross.push_back(tmp);
     96                 tmp.id = i;
     97                 line[j].cross.push_back(tmp);
     98             }
     99         }
    100         for (int i = 0; i < n; i++){
    101             line[i].fix();
    102         }
    103 
    104         int out = 0;
    105 
    106         for (int i = 0; i < n; i++){
    107             int endj = line[i].cross.size();
    108 
    
    109             for (int j = 1; j <endj; j++){
    110                 id[0] = i;
    111                 id[1] = line[i].cross[j - 1].id;
    112                 id[2] = line[i].cross[j].id;
    113                 sort(id, id + 3);
    114                 //cnt.insert(make_pair(make_pair(id[0], id[1]), id[2]));
    115                 if (insert(id)) out++;
    116             }
    117         }
    118         /*
    119         multiset<piii>::iterator ii;
    120         piii pre = make_pair(make_pair(-1, -1), -1);
    121 
    122         for (ii = cnt.begin(); ii != cnt.end(); ii++){
    123             piii tt = (*ii);
    124 
    125             if (tt == pre){
    126                 pre = tt;
    127                 continue;
    128             }
    129             pre = tt;
    130             if (cnt.count(tt) == 3){
    131                 //printf("%d %d %d\n", tt.first.first, tt.first.second, tt.second);
    132                 out++;
    133             }
    134         }
    135         */
    136         /*
    137         for (int i = 0; i < mod; i++){
    138             if (cnt[i] == 3) out++;
    139         }
    140         */
    141         printf("%d\n", out);
    142     }
    143 
    144     return 0;
    145 }


    ——written by Lyon



  • 相关阅读:
    Python2和3的区别
    Linux内核的中断机制
    Linux内核的并发与竞态、信号量、互斥锁、自旋锁
    驱动程序实例(五):LCD驱动程序分析(Samsung LCD)
    Linux字符设备驱动框架(五):Linux内核的framebuffer驱动框架
    驱动程序实例(四):按键驱动程序(platform + input子系统 + 外部中断方式)
    Linux字符设备驱动框架(四):Linux内核的input子系统
    gpiolib库详解
    Linux字符设备驱动框架(三):Linux内核的misc类设备驱动框架
    驱动程序实例(三):蜂鸣器驱动程序(misc类设备驱动框架)
  • 原文地址:https://www.cnblogs.com/LyonLys/p/cf_empty_triangle_Lyon.html
Copyright © 2020-2023  润新知