uva 1606 (计算几何)

这是我人生中的第一个计算几何题,好好收藏一下。

1、当一个点关于远点对称之后,除了两点之间的连线外,其他的任何直线都会讲两点分成两个部分

2、极角排序

3、线的旋转

4、叉积求 sin

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

class Node {
    public:
        int x,y,color;
        double rad;
        bool operator < (const Node& rhs) const {
            return rad < rhs.rad;
        }
}a[1010],p[1010];

// Turn 表示叉积求sin  即 不能超过180
bool Turn(Node& a,Node& b) {
    return a.x * b.y >= a.y * b.x;
}

int main () {
    int N;
    //freopen("1.txt","r",stdin);
    while (cin >> N, N) {
        for (int i = 0;i < N;i++) {
            cin >> a[i].x >> a[i].y >> a[i].color;
        }
        if (N <= 2) {
            cout << N << endl;
            continue;
        }
        int maxn = 0;
        for (int i = 0;i < N;i++) {
            int k = 0;
            for (int j = 0;j < N;j++) {
                if (i != j) {
                    p[k].x = a[j].x - a[i].x;
                    p[k].y = a[j].y - a[i].y;
                    if (a[j].color) { // 原点对称
                        p[k].x = -p[k].x;
                        p[k].y = -p[k].y;
                    }
                    p[k].rad = atan2(p[k].y,p[k].x); // 求弧度
                    k++;
                 }
            }
            sort(p,p + k); // 极角排序
            int L = 0;int ans = 1;
            int R = 0;
            while (L < k) {
                if (L == R) {
                    R = (R + 1) % k;
                    ans ++;
                }
                while (L != R && Turn(p[L],p[R])) { // 不能转过180度 L!=R 是考虑到 如果转过180 回到起始点
                    ans++;
                    R = (R + 1) % k;
                }
                maxn = max(maxn,ans);
                L++;
                ans--;
            }
        }
        cout << maxn << endl;
     }
}

 

posted @ 2015-02-09 10:29  闪光阳  阅读(480)  评论(0编辑  收藏  举报