UVaLive4043 UVa1411 Ants 巨人与鬼

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

法一:暴力

随机一个初始方案,枚举任意两条线段如果有交点就改一下。

效率其实挺好的。

法二:二分图最佳完美匹配

显然没有交点的方案是所有线段的长度和最小的方案,将边权构造为欧几里德距离即可,$O(n^4)$的算法效率远不及法一,$O(n^3)$与法一持平。

 

法三:分治

这是紫书上介绍的方法,每次找出一个最下最左的点,将其他的点相对于这个点进行极角排序,按极角序扫描,当白点和黑点一样多时(算上最下最左那个点),将第一个点和最后一个点配对,递归处理剩下的两部分。时间复杂度大概是$O(n^2log{n})$的?效率最高。

 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
", ans[i] - n);
81         }
82     }
83     
84     return 0;
85 }
分治算法

 

原文地址:https://www.cnblogs.com/showson/p/5197181.html