zoukankan      html  css  js  c++  java
  • 二维计算几何基础题目泛做(SYX第一轮)

    题目1: POJ 2318 TOYS

    题目大意:

    给一个有n个挡板的盒子,从左到右空格编号为0...n。有好多玩具,问每个玩具在哪个空格里面。

    算法讨论:

    直接叉积判断就可以。注意在盒子的边界上面也算在盒子里面。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <iostream>
     5 #include <algorithm>
     6 #include <cmath>
     7 
     8 using namespace std;
     9 
    10 const int M = 5000 + 5;
    11 typedef long long ll;
    12 
    13 int n, m, a, b, c, d;
    14 int vi[M], tim = 0, num[M];
    15 
    16 struct Line {
    17   int zx, zy, yx, yy;
    18 }l[M];
    19 
    20 struct Point {
    21   int x, y;
    22   bool operator < (const Point &h) const {
    23     if(h.x == x) return y < h.y;
    24     return x < h.x;
    25   }
    26 }p[M];
    27 
    28 ll cross(int i, int j) {
    29   return 1LL * (l[i].zx - p[j].x) * (l[i].yy - p[j].y) - 1LL * (l[i].yx - p[j].x) * (l[i].zy - p[j].y);
    30 }
    31 #define ONLINE_JUDGE
    32 
    33 int main() {
    34 #ifndef ONLINE_JUDGE
    35   freopen("t.txt", "r", stdin);
    36   freopen("t.out", "w", stdout);
    37 #endif
    38   
    39   int u, v;
    40   
    41   while(scanf("%d", &n) && n) {
    42     scanf("%d%d%d%d%d", &m, &a, &b, &c, &d);
    43     ++ tim;
    44     memset(num, 0, sizeof num);
    45     for(int i = 1; i <= n; ++ i) {
    46       scanf("%d%d", &u, &v);
    47       l[i].zx = u; l[i].zy = b;
    48       l[i].yx = v; l[i].yy = d;
    49     }
    50     l[0].zx = l[0].yx = a;
    51     l[0].zy = b; l[0].yy = d;
    52     l[n + 1].zx = l[n + 1].yx = c;
    53     l[n + 1].zy = b; l[n + 1].yy = d;
    54     for(int i = 1; i <= m; ++ i) {
    55       scanf("%d%d", &p[i].x, &p[i].y);
    56     }
    57     for(int i = 0; i < n + 1; ++ i) {
    58       for(int j = 1; j <= m; ++ j) {
    59         if(vi[j] == tim) continue;
    60         if(p[j].y == b) {
    61           if(p[j].x >= l[i].zx && p[j].x <= l[i + 1].zx) {
    62             vi[j] = tim;
    63             num[i] ++;
    64           }
    65         }
    66         else if(p[j].y == d) {
    67           if(p[j].x >= l[i].yx && p[j].x <= l[i + 1].yx) {
    68             vi[j] = tim;
    69             num[i] ++;
    70           }
    71         }
    72         else if(i == 0 && p[j].x == a) {
    73           vi[j] = tim;
    74           num[0] ++;
    75         }
    76         else if(i == n && p[j].x == c) {
    77           vi[j] = tim;
    78           num[n] ++;
    79         }
    80         else if(1LL * cross(i, j) * cross(i + 1, j) < 0) {
    81           vi[j] = tim;
    82           num[i] ++;
    83         }
    84       }
    85     }
    86     for(int i = 0; i < n + 1; ++ i) {
    87       printf("%d: %d
    ", i, num[i]);
    88     }
    89     puts("");
    90   }
    91 
    92 #ifndef ONLINE_JUDGE
    93   fclose(stdin); fclose(stdout);
    94 #endif
    95   return 0;
    96 }
    poj 2318

    题目2: POJ 2398 Toys

    题目大意:

    同上。不过不同的是,这里面的挡板输入是没有顺序的,而且问的是有t个玩具的格子有几个。

    算法讨论:

    上个题小小变动一下就可以了。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <iostream>
      5 #include <algorithm>
      6 #include <cmath>
      7 
      8 using namespace std;
      9 
     10 const int M = 5000 + 5;
     11 typedef long long ll;
     12 
     13 int n, m, a, b, c, d;
     14 int vi[M], tim = 0, num[M], out[M];
     15 
     16 struct Line {
     17   int zx, zy, yx, yy;
     18   bool operator < (const Line &h) const {
     19     int lx1 = max(zx, yx), mx1 = min(zx, yx);
     20     int lx2 = max(h.zx, h.yx), mx2 = min(h.zx, h.yx);
     21 
     22     if(mx2 == mx1) {
     23       return lx1 < lx2;
     24     }
     25     return mx1 < mx2;
     26   }
     27 }l[M];
     28 
     29 struct Point {
     30   int x, y;
     31   bool operator < (const Point &h) const {
     32     if(h.x == x) return y < h.y;
     33     return x < h.x;
     34   }
     35 }p[M];
     36 
     37 ll cross(int i, int j) {
     38   return 1LL * (l[i].zx - p[j].x) * (l[i].yy - p[j].y) - 1LL * (l[i].yx - p[j].x) * (l[i].zy - p[j].y);
     39 }
     40 #define ONLINE_JUDGE
     41 
     42 int main() {
     43 #ifndef ONLINE_JUDGE
     44   freopen("t.txt", "r", stdin);
     45   freopen("t.out", "w", stdout);
     46 #endif
     47   
     48   int u, v;
     49   
     50   while(scanf("%d", &n) && n) {
     51     scanf("%d%d%d%d%d", &m, &a, &b, &c, &d);
     52     ++ tim;
     53     memset(num, 0, sizeof num);
     54     memset(out, 0, sizeof out);
     55     for(int i = 1; i <= n; ++ i) {
     56       scanf("%d%d", &u, &v);
     57       l[i].zx = u; l[i].zy = b;
     58       l[i].yx = v; l[i].yy = d;
     59     }
     60     sort(l + 1, l + n + 1);
     61     l[0].zx = l[0].yx = a;
     62     l[0].zy = b; l[0].yy = d;
     63     l[n + 1].zx = l[n + 1].yx = c;
     64     l[n + 1].zy = b; l[n + 1].yy = d;
     65     for(int i = 1; i <= m; ++ i) {
     66       scanf("%d%d", &p[i].x, &p[i].y);
     67     }
     68     for(int i = 0; i < n + 1; ++ i) {
     69       for(int j = 1; j <= m; ++ j) {
     70         if(vi[j] == tim) continue;
     71         if(p[j].y == b) {
     72           if(p[j].x >= l[i].zx && p[j].x <= l[i + 1].zx) {
     73             vi[j] = tim;
     74             num[i] ++;
     75           }
     76         }
     77         else if(p[j].y == d) {
     78           if(p[j].x >= l[i].yx && p[j].x <= l[i + 1].yx) {
     79             vi[j] = tim;
     80             num[i] ++;
     81           }
     82         }
     83         else if(i == 0 && p[j].x == a) {
     84           vi[j] = tim;
     85           num[0] ++;
     86         }
     87         else if(i == n && p[j].x == c) {
     88           vi[j] = tim;
     89           num[n] ++;
     90         }
     91         else if(1LL * cross(i, j) * cross(i + 1, j) < 0) {
     92           vi[j] = tim;
     93           num[i] ++;
     94         }
     95       }
     96     }
     97     for(int i = 0; i < n + 1; ++ i) {
     98       out[num[i]] ++;
     99     }
    100     puts("Box");
    101     for(int i = 1; i <= m; ++ i) {
    102       if(out[i])
    103         printf("%d: %d
    ", i, out[i]);
    104     }
    105   }
    106 
    107 #ifndef ONLINE_JUDGE
    108   fclose(stdin); fclose(stdout);
    109 #endif
    110   return 0;
    111 }
    poj 2398

    题目3: POJ 1654 Area

    题目大意:

    给一个数字序列,每个数字都代表向特定的方向走。求数字围成的多边形的面积。数据保证合法。

    算法讨论:

    直接做就行。注意输出的时候,分类讨论下就可以了。而且注意内存,不能把点存下来,要边读入边计算。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <algorithm>
     5 #include <iostream>
     6 #include <cmath>
     7 
     8 using namespace std;
     9 
    10 const int N = 1000000 + 5;
    11 
    12 int len, cnt;
    13 char str[N];
    14 int dx[]={0, 1, 1, 1, 0, 0, 0, -1, -1, -1};
    15 int dy[]={0, -1, 0, 1, -1, 0, 1, -1, 0, 1};
    16 
    17 double cross(double a, double b, double c, double d) {
    18   return a * d - b * c;
    19 }
    20 
    21 int main() {
    22   int t;
    23 
    24   scanf("%d", &t);
    25 
    26   while(t --) {
    27     scanf("%s", str + 1);
    28     len = strlen(str + 1);
    29 
    30     double last_x = 0, last_y = 0;
    31     double area = 0;
    32     
    33     for(int i = 1; i <= len; ++ i) {
    34       int q = str[i] - '0';
    35 
    36       if(q == 5) {
    37         break;
    38       }
    39       area += cross(last_x, last_y, last_x + dx[q], last_y  + dy[q]);
    40       last_x += dx[q]; last_y += dy[q];
    41     }
    42 
    43     if((int)area & 1)
    44       printf("%.0lf.5
    ", floor(fabs(area) / 2));
    45     else
    46       printf("%.0lf
    ", fabs(area) / 2);
    47   }
    48   return 0;
    49 }
    POJ 1654

    题目4: POJ 1269 Intersecting Lines

    题目大意:

    给出直线对,判断这对直线的关系:平行,重合或者相交。

    算法讨论:

    假设直线1的两个点编号为1,2,直线2的两个点编号为3,4,如果 1,2,4的叉积为0, 1,2,3的叉积为0,则说明重合。

    如果不重合,用两点式算斜率,为了避免除0错误,把两边除法比较变形为乘法。

    如果不重合也不平行,就相交,用分点定理找交点。我的代码中只有规范相交的部分。具体代码请见刘汝佳《算法艺术与信息学竞赛》P357页。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <algorithm>
     5 #include <iostream>
     6 #include <cmath>
     7 
     8 using namespace std;
     9 
    10 const double eps = 1e-5;
    11 
    12 int n;
    13 
    14 struct Point {
    15   double a, b;
    16   Point(double _a = 0, double _b = 0):
    17     a(_a), b(_b) {}
    18 }c[5];
    19 
    20 double cross(int i, int j, int k) {
    21   return (c[i].a - c[k].a) * (c[j].b - c[k].b) - (c[j].a - c[k].a) * (c[i].b - c[k].b);
    22 }
    23 
    24 int dcmp(double s) {
    25   return s > eps ? 1 : (s < -eps ? -1 : 0);
    26 }
    27 
    28 void solve() {
    29   if(fabs(cross(1, 2, 3)) <= eps && fabs(cross(1, 2, 4)) <= eps) puts("LINE");
    30   else if((c[2].b - c[1].b) * (c[4].a - c[3].a) == (c[2].a - c[1].a) * (c[4].b - c[3].b))
    31     puts("NONE");
    32   else {
    33     double s1 = cross(1, 2, 3), s2 = cross(1, 2, 4);
    34     double x = (c[3].a * s2 - c[4].a * s1) / (s2 - s1);
    35     double y = (c[3].b * s2 - c[4].b * s1) / (s2 - s1);
    36     
    37     printf("POINT %.2f %.2f
    ", x, y);
    38   }
    39 }
    40 
    41 int main() {
    42   double a, b;
    43   
    44   puts("INTERSECTING LINES OUTPUT");
    45   scanf("%d", &n);
    46   for(int i = 1; i <= n; ++ i) {
    47     for(int j = 1; j <= 4; ++ j) {
    48       scanf("%lf%lf", &a, &b);
    49       c[j] = Point(a, b);
    50     }
    51     solve();
    52   }
    53   puts("END OF OUTPUT");
    54   return 0;
    55 }
    POJ 1269

    题目5: POJ 1113 Wall

    题目大意:

    求给出点集的凸包长度+一个半径为r的圆的周长和。

    算法讨论:

    看了下面这个图,你就什么都明白了。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <iostream>
     5 #include <algorithm>
     6 #include <cmath>
     7 
     8 #define pi 3.1415926535
     9 
    10 using namespace std;
    11 
    12 const int N = 1000 + 5;
    13 const double eps = 1e-6;
    14 
    15 int n, l;
    16 double ans = 0;
    17 
    18 struct Point {
    19   double x, y;
    20 }p[N], st[N];
    21 
    22 double dist(Point a, Point b) {
    23   return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
    24 }
    25 
    26 double cross(Point a, Point b, Point c) {
    27   return (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y);
    28 }
    29 
    30 bool cmp(Point a, Point b) {
    31   if(cross(a, b, p[0]) == 0)
    32     return dist(a, p[0]) < dist(b, p[0]);
    33   return cross(a, b, p[0]) > 0;
    34 }
    35 
    36 void Graham() {
    37   int top = 2, k = 0;
    38 
    39   for(int i = 1; i < n; ++ i) {
    40     if(p[i].x < p[k].x || (p[i].x == p[k].x && p[i].y < p[k].y))
    41       k = i;
    42   }
    43   swap(p[k], p[0]);
    44   sort(p + 1, p + n, cmp);
    45   st[0] = p[0]; st[1] = p[1]; st[2] = p[2];
    46   for(int i = 3; i < n; ++ i) {
    47     while(top && cross(p[i], st[top], st[top - 1]) >= 0) top --;
    48     st[++ top] = p[i];
    49   }
    50   st[++ top] = p[0];
    51   for(int i = 0; i < top; ++ i)
    52     ans += dist(st[i], st[i + 1]);
    53 }
    54 
    55 int main() {
    56   scanf("%d%d", &n, &l);
    57   for(int i = 0; i < n; ++ i) {
    58     scanf("%lf%lf", &p[i].x, &p[i].y);
    59   }
    60   Graham();
    61   printf("%.0f", (double) ans + (double) 2 * pi * l);
    62   return 0;
    63 }
    POJ 1113

    题目6: POJ 3304 Segments

    题目大意:

    给出N个线段,是否有存在一条直线与所有线段都相交。

    算法讨论:

    这个直线一定经过线段的两个端点。所以我们枚举端点然后判断是否与每条线段相交即可。

    判断相交的方法,用跨立实验。如果直线上的两个点与线段的两个点的叉积大于0,说明相交。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <iostream>
     5 #include <algorithm>
     6 #include <cmath>
     7 
     8 using namespace std;
     9 
    10 const int N = 100 + 5;
    11 const double eps = 1e-8;
    12 
    13 int n, cnt;
    14 
    15 struct Line {
    16   double a, b, c, d;
    17 }l[N];
    18 struct Point {
    19   double x, y;
    20 }p[N<<1];
    21 double cross(int i, int j, int k) {
    22   double t1 = (p[i].x - l[k].a) * (p[j].y - l[k].b) - (p[j].x - l[k].a) * (p[i].y - l[k].b);
    23   double t2 = (p[i].x - l[k].c) * (p[j].y - l[k].d) - (p[j].x - l[k].c) * (p[i].y - l[k].d);
    24   return t1 * t2;
    25 }
    26 int main() {
    27   int t;
    28 
    29   scanf("%d", &t);
    30 
    31   while(t --) {
    32     cnt = 0;
    33     scanf("%d", &n);
    34     for(int i = 1; i <= n; ++ i) {
    35       scanf("%lf%lf%lf%lf", &l[i].a, &l[i].b, &l[i].c, &l[i].d);
    36       p[++ cnt].x = l[i].a; p[cnt].y = l[i].b;
    37       p[++ cnt].x = l[i].c; p[cnt].y = l[i].d;
    38     }
    39     if(n == 1 || n == 2) {
    40       puts("Yes!");
    41       continue;
    42     }
    43     for(int i = 1; i <= cnt; ++ i) {
    44       for(int j = i + 1; j <= cnt; ++ j) {
    45         if(fabs(p[i].x - p[j].x) < eps && fabs(p[i].y - p[j].y) < eps) continue;
    46         for(int k = 1; k <= n; ++ k) {
    47           if(cross(i, j, k) > 0) {
    48             break;
    49           }
    50           if(k == n) {
    51             puts("Yes!");
    52             goto A;
    53           }
    54         }
    55       }
    56     }
    57     puts("No!");
    58     A:;
    59   }
    60 
    61   return 0;
    62 }
    POJ 3304

    题目7: POJ 2187 Beauty Conteset

    题目大意:

    求平面点集最远点距离平方。

    算法讨论:

    旋转卡壳直接上吧。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <algorithm>
     5 #include <iostream>
     6 #include <cmath>
     7 
     8 using namespace std;
     9 
    10 const int N = 50000 + 5;
    11 
    12 int n, top = 2;
    13 double ans;
    14 
    15 struct Point {
    16   double x, y;
    17 }p[N], st[N];
    18 
    19 double dist(Point a, Point b) {
    20   return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
    21 }
    22 
    23 double cross(Point a, Point b, Point c) {
    24   return (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y);
    25 }
    26 
    27 double cal(Point a, Point b) {
    28   return pow(a.x - b.x, 2) + pow(a.y - b.y, 2);
    29 }
    30 
    31 bool cmp(Point a, Point b) {
    32   if(cross(a, b, p[0]) == 0)
    33     return dist(a, p[0]) < dist(b, p[0]);
    34   return cross(a, b, p[0]) > 0;
    35 }
    36 
    37 void Graham() {
    38   int k = 0;
    39 
    40   for(int i = 1; i < n; ++ i)
    41     if(p[i].x < p[k].x || (p[i].x == p[k].x && p[i].y < p[k].y))
    42       k = i;
    43   swap(p[0], p[k]);
    44   sort(p + 1, p + n, cmp);
    45   st[0] = p[0]; st[1] = p[1]; st[2] = p[2];
    46   for(int i = 3; i < n; ++ i) {
    47     while(top && cross(p[i], st[top], st[top - 1]) >= 0) top --;
    48     st[++ top] = p[i];
    49   }
    50   st[++ top] = p[0];
    51 }
    52 
    53 void rotate() {
    54   int q = 1;
    55 
    56   for(int i = 0; i < top; ++ i) {
    57     while(cross(st[i + 1], st[q + 1], st[i]) > cross(st[i + 1], st[q], st[i]))
    58       q = (q + 1) % top;
    59     ans = max(ans, max(cal(st[i], st[q]), cal(st[i + 1], st[q + 1])));
    60   }
    61 }
    62 
    63 int main() {
    64   scanf("%d", &n);
    65   for(int i = 0; i < n; ++ i) {
    66     scanf("%lf%lf", &p[i].x, &p[i].y);
    67   }
    68   Graham();
    69   rotate();
    70   printf("%.0f", ans);
    71   return 0;
    72 }
    POJ 2187

    题目8: POJ 1584 A Round Peg in a Ground Hole

    题目大意:

    给一个圆和一些点。你要做三件事:判断这些点是否组成一个凸多边形。 圆的圆心是否在多边形内。 圆是否在凸多边形内。

    算法讨论:

    对于第一个件事,我们直接做Graham然后看有多少个点在凸包上。注意排序的时候,如果三个点在一个竖线上的情况要在cmp函数里面判断一下。

    对于第二件事,由于这是一个凸多边形,所以我们用回转角法来判断是否在多边形内。注意这里eps不要取的太小,否则会被卡精度。

    对于第三件事,最简单的,直接算距离,注意相切的情况也算在多边形内部。

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <cmath>
      7 
      8 #define pi 3.1415926535
      9 
     10 using namespace std;
     11 
     12 const int N = 100000 + 5;
     13 const double eps = 1e-5;
     14   
     15 int n, top = 2;
     16 double cx, cy, cr;
     17 
     18 struct Point {
     19   double x, y;
     20 }p[N], st[N];
     21 
     22 double dist(Point a, Point b) {
     23   return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
     24 }
     25 
     26 double cross(Point a, Point b, Point c) {
     27   return (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);
     28 }
     29 
     30 bool cmp(Point a, Point b) {
     31   if(cross(a, b, p[0]) == 0) {
     32     if(a.x == b.x && a.x == p[0].x)
     33       return dist(a, p[0]) > dist(b, p[0]);
     34     else
     35       return dist(a, p[0]) < dist(b, p[0]);
     36   }
     37   return cross(a, b, p[0]) > 0;
     38 }
     39 
     40 void Graham() {
     41   int k = 0;
     42   
     43   top = 2;
     44   for(int i = 1; i < n; ++ i) {
     45     if(p[i].x < p[k].x || (p[i].x == p[k].x && p[i].y < p[k].y))
     46       k = i;
     47   }
     48   swap(p[k], p[0]);
     49   sort(p + 1, p + n, cmp);
     50   st[0] = p[0]; st[1] = p[1]; st[2] = p[2];
     51   for(int i = 3; i < n; ++ i) {
     52     while(top && cross(p[i], st[top], st[top - 1]) > 0) top --;
     53     st[++ top] = p[i];
     54   }
     55   st[++ top] = p[0];
     56 }
     57 
     58 double len(int i) {
     59   return sqrt(pow(st[i].x - cx, 2) + pow(st[i].y - cy, 2));
     60 }
     61 
     62 double cal(int i, int j) {
     63   double t1 = (st[i].x - cx) * (st[j].x - cx) + (st[i].y - cy) * (st[j].y - cy);
     64   double t2 = len(i) * len(j);
     65 
     66   return t1 / t2;
     67 }
     68 
     69 int main() {
     70   while(1) {
     71     scanf("%d", &n);
     72     if(n < 3) break;
     73     scanf("%lf%lf%lf", &cr, &cx, &cy);
     74     for(int i = 0; i < n; ++ i) {
     75       scanf("%lf%lf", &p[i].x, &p[i].y);
     76     }
     77     Graham();
     78     if(top != n) {
     79       puts("HOLE IS ILL-FORMED");
     80       continue;
     81     }
     82 
     83     double tmp = 0;
     84     bool flag = false;
     85     
     86     for(int i = 0; i < top; ++ i) {
     87       tmp += (double)acos(cal(i, i + 1)) * 180 / pi;
     88     }
     89     if(fabs(tmp - 360.00000) > eps) {
     90       puts("PEG WILL NOT FIT");
     91       continue;
     92     }
     93     for(int i = 0; i < top; ++ i) {
     94       tmp = (st[i].x - cx) * (st[i + 1].y - cy) - (st[i + 1].x - cx) * (st[i].y - cy);
     95       tmp = fabs(tmp);
     96       tmp = tmp / dist(st[i], st[i + 1]);
     97       if(tmp - cr < -eps) {
     98         flag = true;
     99         break;
    100       }
    101     }
    102     if(flag) {
    103       puts("PEG WILL NOT FIT");
    104     }
    105     else {
    106       puts("PEG WILL FIT");
    107     }
    108   }
    109   return 0;
    110 }
    POJ 1584

    题目9: POJ 2079 Triangle

    题目大意:

    求点集中面积最大的三角形面积。

    算法讨论:

    类似旋转卡壳的算法。感觉这是个模板题。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <iostream>
     5 #include <algorithm>
     6 #include <cmath>
     7 
     8 using namespace std;
     9 
    10 const int N = 50000 + 5;
    11 
    12 int n, top;
    13 double ans = 0;
    14 
    15 struct Point {
    16   double x, y;
    17 }p[N], st[N];
    18 
    19 double dist(Point a, Point b) {
    20   return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
    21 }
    22 
    23 double cross(Point a, Point b, Point c) {
    24   return (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);
    25 }
    26 
    27 bool cmp(Point a, Point b) {
    28   if(cross(a, b, p[0]) == 0)
    29     return dist(a, p[0]) < dist(b, p[0]);
    30   return cross(a, b, p[0]) > 0;
    31 }
    32 
    33 void Graham() {
    34   int k = 0; top = 2;
    35 
    36   for(int i = 1; i < n; ++ i) {
    37     if(p[i].x < p[k].x || (p[i].x == p[k].x && p[i].y < p[k].y))
    38       k = i;
    39   }
    40   swap(p[0], p[k]);
    41   sort(p + 1, p + n, cmp);
    42   st[0] = p[0]; st[1]= p[1]; st[2] = p[2];
    43   for(int i = 3; i < n; ++ i) {
    44     while(top && cross(p[i], st[top], st[top - 1]) >= 0)top --;
    45     st[++ top] = p[i];
    46   }
    47   st[++ top] = p[0];
    48 }
    49 
    50 void rotate_triangle() {
    51   int i, j, k, kk;
    52 
    53   for(i = 0; i < top; ++ i) {
    54     j = (i + 1) % top;
    55     k = (j + 1) % top;
    56     while(k != i && cross(st[i], st[j], st[k]) < cross(st[i], st[j], st[k + 1]))
    57       k = (k + 1) % top;
    58     if(k == i) continue;
    59     kk = (k + 1) % top;
    60     while(j != kk && k != i) {
    61       ans = max(ans, fabs(cross(st[i], st[j], st[k])));
    62       while(k != i && cross(st[i], st[j], st[k]) < cross(st[i], st[j], st[k + 1]))
    63         k = (k + 1) % top;
    64       j = (j + 1) % top;
    65     }
    66   }
    67 }
    68 
    69 int main() {
    70   while(scanf("%d", &n) && n > 0) {
    71     ans = 0;
    72     for(int i = 0; i < n; ++ i) {
    73       scanf("%lf%lf", &p[i].x, &p[i].y);
    74     }
    75     Graham();
    76     rotate_triangle();
    77     printf("%.2f
    ", (double) ans / 2);
    78   }
    79 
    80   return 0;
    81 }
    POJ 2079

    题目10: POJ 2653 Pick-up sticks

    题目大意:

    给一坨线段,问哪里线段可以被看到。

    算法讨论:

    在网上看到了两种解法,一个是O(N^2)的暴力,但是不知道为什么对于10W的数据可以跑过。就是枚举每一个线段i,如果有线段和其相交,

    那么这个线段就是不可见。

    另一个解法就是对于当前线段,判断其是否与队列中的线段有交点,如果有,把有交点的那个线段出队,把这个入队,否则两个一起入队。

    看样子是一样的方法啊。我的代码还是没有不规范判断相交的部分。

     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cstdio>
     6 #include <cmath>
     7 
     8 using namespace std;
     9 
    10 const int N = 100000 + 5;
    11 const double eps = 1e-6;
    12 
    13 int n;
    14 bool flag[N];
    15 
    16 struct Point {
    17   double x, y;
    18   Point(double _x = 0, double _y = 0):
    19     x(_x), y(_y) {}
    20 };
    21 struct Line {
    22   Point A, B;
    23 }l[N];
    24 
    25 double cross(Point a, Point b, Point c) {
    26   return (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);
    27 }
    28 
    29 int dcmp(double x) {
    30   return x > eps ? 1 : (x < -eps ? -1 : 0);
    31 }
    32 
    33 int segcross(Point a, Point b, Point c, Point d) {
    34   int d1, d2, d3, d4;
    35 
    36   d1 = dcmp(cross(a, b, c));
    37   d2 = dcmp(cross(a, b, d));
    38   d3 = dcmp(cross(c, d, a));
    39   d4 = dcmp(cross(c, d, b));
    40 
    41   if((d1 ^ d2) == -2 && (d3 ^ d4) == -2)
    42     return 1;
    43   return 0;
    44 }
    45 
    46 int main() {
    47   double a, b, c, d;
    48   
    49   while(scanf("%d", &n) && n) {
    50     for(int i = 1; i <= n; ++ i ) {
    51       scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
    52       l[i].A = (Point){a, b};
    53       l[i].B = (Point){c, d};
    54       flag[i] = true;
    55     }
    56     for(int i = 1; i <= n; ++ i) {
    57       for(int j = i + 1; j <= n; ++ j) {
    58         if(segcross(l[i].A, l[i].B, l[j].A, l[j].B)) {
    59           flag[i] = false;
    60           break;
    61         }
    62       }
    63     }
    64     bool tmp = false;
    65     
    66     printf("Top sticks: ");
    67     for(int i = 1; i <= n; ++ i) {
    68       if(flag[i]) {
    69         if(!tmp) {
    70           printf("%d", i);
    71           tmp = true;
    72         }
    73         else {
    74           printf(", %d", i);
    75         }
    76       } 
    77     }
    78     puts(".");
    79   }
    80 
    81   return 0;
    82 }
    POJ 2653
  • 相关阅读:
    帝国 标签模板 使用程序代码 去除html标记 并 截取字符串
    iis6 伪静态 iis配置方法 【图解】
    您来自的链接不存在 帝国CMS
    帝国cms Warning: Cannot modify header information headers already sent by...错误【解决方法】
    .fr域名注册 51元注册.fr域名
    帝国网站管理系统 恢复栏目目录 建立目录不成功!请检查目录权限 Godaddy Windows 主机
    星外虚拟主机管理平台 开通数据库 出现Microsoft OLE DB Provider for SQL Server 错误 '8004' 从字符串向 datetime 转换失败
    ASP.NET 自定义控件学习研究
    CSS层叠样式表之CSS解析机制的优先级
    ASP.NET程序员工作面试网络收藏夹
  • 原文地址:https://www.cnblogs.com/sxprovence/p/5191853.html
Copyright © 2011-2022 走看看