标签:
题意:给出平面上n个白点n个黑点,要求两两配对,且配对所连线段没有交点。
法一:暴力
随机一个初始方案,枚举任意两条线段如果有交点就改一下。
效率其实挺好的。
法二:二分图最佳完美匹配
显然没有交点的方案是所有线段的长度和最小的方案,将边权构造为欧几里德距离即可,O(n4)的算法效率远不及法一,O(n3)与法一持平。
法三:分治
这是紫书上介绍的方法,每次找出一个最下最左的点,将其他的点相对于这个点进行极角排序,按极角序扫描,当白点和黑点一样多时(算上最下最左那个点),将第一个点和最后一个点配对,递归处理剩下的两部分。时间复杂度大概是O(n2logn)的?效率最高。
1 #include<cstdio>
2 #include<cstring>
3 #include<cstdlib>
4 #include<algorithm>
5 #include<iostream>
6
7 using namespace std;
8 const int N = 100 + 10;
9
10 #include<cmath>
11 struct Point {
12 int x, y;
13 Point() {}
14 Point(int x, int y) : x(x), y(y) {}
15 double angle(const Point& p) const {
16 return atan2(y - p.y, x - p.x);
17 }
18 bool operator < (const Point &rhs) const {
19 return y < rhs.y || (y == rhs.y && x < rhs.x);
20 }
21 void read() {
22 scanf("%d%d", &x, &y);
23 }
24 };
25
26 int n;
27 struct Node {
28 Point p;
29 int id;
30 double ang;
31
32 bool operator < (const Node &rhs) const {
33 return ang < rhs.ang;
34 }
35
36 void getangle(const Point& p0) {
37 ang = p.angle(p0);
38 }
39
40 int type() const {
41 return id <= n ? 1 : -1;
42 }
43 }p[N * 2];
44
45 int ans[N * 2];
46
47 void solve(int l, int r) {
48 if(l > r) return;
49 int pos = l;
50 for(int i = l + 1; i <= r; i++) {
51 if(p[i].p < p[pos].p) pos = i;
52 }
53 swap(p[pos], p[l]);
54 int cnt = p[l].type();
55 for(int i = l + 1; i <= r; i++) {
56 p[i].getangle(p[l].p);
57 }
58 sort(p + l + 1, p + r + 1);
59 for(int i = l + 1; i <= r; i++) {
60 cnt += p[i].type();
61 if(!cnt) {
62 ans[p[l].id] = p[i].id;
63 ans[p[i].id] = p[l].id;
64 solve(l + 1, i - 1);
65 solve(i + 1, r);
66 return;
67 }
68 }
69 }
70
71 int main() {
72 while(scanf("%d", &n) == 1) {
73 for(int i = 1; i <= (n << 1); i++) {
74 p[i].p.read();
75 p[i].id = i;
76 }
77
78 solve(1, n << 1);
79 for(int i = 1; i <= n; i++) {
80 printf("%d\n", ans[i] - n);
81 }
82 }
83
84 return 0;
85 }
标签:
原文地址:http://www.cnblogs.com/showson/p/5197181.html