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 }
代码君

 

你可能感兴趣的:(uva)