UVa 1606 (极角排序) Amphiphilic Carbon Molecules

如果,没有紫书上的翻译的话,我觉得我可能读不懂这道题。=_=||

题意:

平面上有n个点,不是白点就是黑点。现在要放一条直线,使得直线一侧的白点与另一侧的黑点加起来数目最多。直线上的点可以看作位于直线的任意一侧。

分析:

首先假设直线经过两个点,否则可以移动直线使其经过两个点,并且总数不会减少。

所以,我们可以先枚举一个基点,然后以这个点为中心。

围绕基点将其他点按照极角排序,将直线旋转,统计符合要求的点的个数。

 

小技巧:

如果将所有的黑点以基点为中心做一个中心对称,则符合要求的点的个数就变成了直线一侧的点的个数。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 1000 + 10;
 6 
 7 int n, color[maxn];
 8 
 9 struct Point
10 {
11     int x, y;
12     Point(int x=0, int y=0):x(x), y(y) {}
13     double rad;
14     bool operator < (const Point& rhs) const
15     { return rad < rhs.rad; }
16 }op[maxn], p[maxn];
17 
18 Point operator - (const Point& A, const Point& B)
19 { return Point(A.x-B.x, A.y-B.y); }
20 
21 int Cross(const Point& A, const Point& B)
22 { return A.x*B.y - A.y*B.x; }
23 
24 int solve()
25 {
26     //if(n <= 3) return n;
27     int ans = 0;
28     for(int i = 0; i < n; ++i)
29     {//枚举基点
30         int k = 0;
31         for(int j = 0; j < n; ++j) if(i != j)
32         {
33             p[k] = op[j] - op[i];
34             if(color[j]) { p[k].x = -p[k].x; p[k].y = -p[k].y; }//将黑点做个中心对称
35             p[k].rad = atan2(p[k].y, p[k].x);
36             k++;
37         }
38         sort(p, p+k);
39 
40         int L = 0, R = 0, cnt = 2;
41         for(; L < k; ++L)
42         {//统计p[L]到p[R]之间的点
43             if(L == R) { R = (R+1)%k; cnt++; }
44             while(L != R && Cross(p[L], p[R]) >= 0) { R = (R+1)%k; cnt++; }//当区间大于180度停止
45             cnt--;
46             ans = max(ans, cnt);
47         }
48     }
49     return ans;
50 }
51 
52 int main()
53 {
54     freopen("in.txt", "r", stdin);
55 
56     while(scanf("%d", &n) == 1 && n)
57     {
58         for(int i = 0; i < n; ++i) scanf("%d%d%d", &op[i].x, &op[i].y, &color[i]);
59         printf("%d\n", solve());
60     }
61 
62     return 0;
63 }
代码君

 

posted @ 2015-02-06 20:04 AOQNRMGYXLMV 阅读(...) 评论(...) 编辑 收藏