hdu 2907 Diamond Dealer (Convex Hull)

Problem - 2907

  简单的凸包加上扫描顶点。

  题意是给出一个多边形,对这个多边形构造一个凸包,问有多少条边是在凸包上的,凸包上有多少个区域是缺了的。求出来以后乘以给出的权值,就是答案。

  做法很简单,对给出的多边形求一次凸包,然后将原多边形的顶点顺序倒序(这是因为我的凸包是逆时针构建的),然后对齐凸包上的第一个点(一定存在能被对其的顶点,阴为在凸包上的点都在原多边形上)。然后从这个点开始扫描,如果凸包上两个点是相邻的,同时这两个点在原多边形上也是相邻的,那么这两个点之间那条边就是凸包上的边,否则就有一个缺失了的区域了。

代码如下:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 #include <iostream>
 6 #include <vector>
 7 
 8 using namespace std;
 9 
10 struct Point {
11     int x, y;
12     Point() {}
13     Point(int x, int y) : x(x), y(y) {}
14 } ;
15 bool operator < (Point x, Point y) { return x.x - y.x < 0 || x.x - y.x == 0 && x.y - y.y < 0;}
16 bool operator == (Point x, Point y) { return x.x - y.x == 0 && x.y - y.y == 0;}
17 Point operator + (Point x, Point y) { return Point(x.x + y.x, x.y + y.y);}
18 Point operator - (Point x, Point y) { return Point(x.x - y.x, x.y - y.y);}
19 
20 inline int crossDet(Point a, Point b) { return a.x * b.y - a.y * b.x;}
21 inline int crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);}
22 inline int dotDet(Point a, Point b) { return a.x * b.x + a.y * b.y;}
23 
24 int andrew(Point *pt, int n, Point *ch) {
25     sort(pt, pt + n);
26     int m = 0;
27     for (int i = 0; i < n; i++) {
28         while (m > 1 && crossDet(ch[m - 2], ch[m - 1], pt[i]) <= 0) m--;
29         ch[m++] = pt[i];
30     }
31     int k = m;
32     for (int i = n - 2; i >= 0; i--) {
33         while (m > k && crossDet(ch[m - 2], ch[m - 1], pt[i]) <= 0) m--;
34         ch[m++] = pt[i];
35     }
36     if (n > 1) m--;
37     return m;
38 }
39 
40 const int N = 55;
41 Point pt[N], ch[N], tmp[N];
42 
43 int main() {
44 //    freopen("in", "r", stdin);
45     int p, q, n, T;
46     cin >> T;
47     while (T-- && cin >> p >> q >> n) {
48         for (int i = 0; i < n; i++) { cin >> pt[i].x >> pt[i].y; tmp[i] = pt[i];}
49         int m = andrew(tmp, n, ch);
50         reverse(pt, pt + n); // 反向原多边形
51         while (!(pt[0] == ch[0])) rotate(pt, pt + 1, pt + n); // 对齐其始点
52         pt[n] = pt[0], ch[m] = ch[0];
53 //        for (int i = 0; i < m; i++) cout << ch[i].x << ' ' << ch[i].y << endl;
54 //        puts("~~~~~");
55 //        for (int i = 0; i < n; i++) cout << pt[i].x << ' ' << pt[i].y << endl;
56 //        puts("!!!!!");
57         int dents = 0, faces = 0;
58         for (int i = 1, j = 1; i <= m; i++) { // 凸包上的顶点顺序枚举一次,统计出结果
59             while (!(ch[i] == pt[j])) j++;
60             if (ch[i - 1] == pt[j - 1]) faces++;
61             else dents++;
62         }
63         cout << max(0, - dents * p + faces * q) << endl;
64     }
65     return 0;
66 }
View Code

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/hdu_2907_Lyon.html