1411

参考博客

紫薯P230

题意:给出平面上n个白点n个黑点,要求两两配对,且配对所连线段没有交点。

紫薯思路:找出y坐标最小的点,如果多个,考虑x最小的。将其他点相对于这个点按极角从小到大排序,然后开始扫描,当白点和黑点一样多时(算上最下面的点),第一个和最后一个匹配,然后递归匹配中间的和外边这两部分

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <cstdio>
 6 using namespace std;
 7 const int N = 100 + 10;
 8 int n;
 9 struct Point
10 {
11     int x, y;
12     Point() {}
13     Point(int x, int y) : x(x), y(y) {}
14     double angle(const Point& p) const // 求极角
15     {
16         return atan2(y - p.y, x - p.x);
17     }
18     bool operator< (const Point& p) const // 定义 < 
19     {
20         return y < p.y || (y == p.y && x < p.x);
21     }
22     void read() // 读入坐标
23     {
24         scanf("%d%d", &x, &y);
25     }
26 };
27 struct Node
28 {
29     Point p; // 每一个点包含x,y坐标
30     int id;
31     double ang; // 与标准点的极角
32     bool operator< (const Node& node) const // 定义Node的<,按极角从小到大排序
33     {
34         return ang < node.ang;
35     }
36     void getAngle(const Node& node)
37     {
38         ang = p.angle(node.p);
39     }
40     int type() // 如果是黑点(白点) 返回1,否则返回-1,判断黑点和白点数量相等时使用
41     {
42         return id <= n ? 1 : -1;
43     }
44 }p[N * 2];
45 int ans[N * 2]; // 配对表
46 void solve(int l, int r)
47 {
48     if (l > r)
49         return;
50     int pos = l; 
51     for (int i = l + 1; i <= r; i++)
52     {
53         if (p[i].p < p[pos].p)
54             pos = i;
55     }
56     swap(p[l], p[pos]); // 让怕p[l]成为最下面的点,y最小
57     int cnt = p[l].type(); 
58     for (int i = l + 1; i <= r; i++)  // 求出所有点与标准的极角大小
59     {
60         p[i].getAngle(p[l]);  
61     }
62     sort(p + l + 1, p + r + 1);  // 按极角从小到大排序
63     for (int i = l + 1; i <= r; i++)
64     {
65         cnt += p[i].type();
66         if (!cnt)  // 黑点和白点相等时 cnt == 0
67         {
68             ans[ p[i].id ] = p[l].id; // 此时的第一个 和 最后一个配对
69             ans[ p[l].id ] = p[i].id;
70             solve(l + 1, i - 1);  // 解决内部的
71             solve(i + 1, r); // 解决外部的
72             return;
73         }
74     }
75 }
76 int main()
77 {
78     while (scanf("%d", &n) != EOF)
79     {
80         for (int i = 1; i <= (n << 1); i++)
81         {
82             p[i].p.read();
83             p[i].id = i;
84         }
85         solve(1, n << 1);
86         for (int i = 1; i <= n; i++)
87         {
88             printf("%d
", ans[i] - n);
89         }
90     }
91     return 0;
92 }
View Code
原文地址:https://www.cnblogs.com/zhaopAC/p/6271136.html