UVaLive4043 UVa1411 Ants 巨人与鬼

题意:给出平面上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 }
分治算法

 

你可能感兴趣的:(UVaLive4043 UVa1411 Ants 巨人与鬼)