Fencing the Cows [USACO]

这道题目是很标准的凸包问题,看了第五章开头的说明,照着写就好。 判断向量夹角用交叉积,右手螺旋,注意交叉积不满足交换率,所以要注意前后顺序。

 

/*
ID: zhangyc1
LANG: C++
TASK: fc
*/
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;

struct SPoint 
{
    double x, y, theta;
};
SPoint arrPoint[10000], centerPoint;
int arrChosen[10000];
int N;

int compare(const void* argv1, const void* argv2)
{
    if (((SPoint*)argv1)->theta < ((SPoint*)argv2)->theta)
        return -1;
    else if (((SPoint*)argv1)->theta > ((SPoint*)argv2)->theta)
        return 1;
    else return 0;
}

inline bool IsAngleConvex(SPoint& P1, SPoint& Pc, SPoint& P3)
{
    // Convex : (P3 - PC) X (P1 - PC) > 0 
    return (P3.x - Pc.x) * (P1.y - Pc.y) - (P3.y - Pc.y) * (P1.x - Pc.x) > 0;
}

void GiftWrapping()
{
    // 选前两个点
    arrChosen[0] = 0, arrChosen[1] = 1;
    int nIdx = 2, nCur = 1, nSt = 0;
    // 选中间节点
    while (nIdx < N)
    {
        while (nCur > 0 && !IsAngleConvex(arrPoint[arrChosen[nCur - 1]], arrPoint[arrChosen[nCur]], arrPoint[nIdx]))
            nCur--;
        arrChosen[++nCur] = nIdx;
        nIdx++;
    }
    // 选最后一个节点
    while (1)
    {
        // ncur-1, ncur, nst 不为凹
        if (nCur - nSt > 2 && !IsAngleConvex(arrPoint[arrChosen[nCur - 1]], arrPoint[arrChosen[nCur]], arrPoint[arrChosen[nSt]]))
        {
            nCur--;
            continue;
        }

        // ncur, nst, nst+1 不为凹
        if (nCur - nSt > 2 && !IsAngleConvex(arrPoint[arrChosen[nCur]], arrPoint[arrChosen[nSt]], arrPoint[arrChosen[nSt + 1]]))
            nSt++;
        else
            break;
    }

    // 计算周长
    double dbLen = sqrt((arrPoint[arrChosen[nSt]].x - arrPoint[arrChosen[nCur]].x) * (arrPoint[arrChosen[nSt]].x - arrPoint[arrChosen[nCur]].x) +
        (arrPoint[arrChosen[nSt]].y - arrPoint[arrChosen[nCur]].y) * (arrPoint[arrChosen[nSt]].y - arrPoint[arrChosen[nCur]].y));
    for (int i = nSt + 1; i <= nCur; i++)
    {
        dbLen += sqrt((arrPoint[arrChosen[i]].x - arrPoint[arrChosen[i - 1]].x) * (arrPoint[arrChosen[i]].x - arrPoint[arrChosen[i - 1]].x) +
            (arrPoint[arrChosen[i]].y - arrPoint[arrChosen[i - 1]].y) * (arrPoint[arrChosen[i]].y - arrPoint[arrChosen[i - 1]].y));
    }
    printf("%.2lf\n", dbLen);
}

void prepairData()
{
    scanf("%d", &N);
    centerPoint.x = centerPoint.y = 0.0;
    for (int i = 0; i < N; i++)
    {
        scanf("%lf%lf", &arrPoint[i].x, &arrPoint[i].y);
        centerPoint.x += arrPoint[i].x;
        centerPoint.y += arrPoint[i].y;
    }
    centerPoint.x /= N;
    centerPoint.y /= N;
}

void process()
{
    for (int i = 0; i < N; i++)
    {
        arrPoint[i].theta = atan2(arrPoint[i].y - centerPoint.y, arrPoint[i].x - centerPoint.x);
    }
    qsort(arrPoint, N, sizeof(SPoint), compare);
    GiftWrapping();
}

int main(){
    freopen("fc.in","r",stdin);
    freopen("fc.out","w",stdout);
    prepairData();
    process();
    return 0;
}

 

 

posted @ 2013-04-19 12:23  J.Z's World  阅读(164)  评论(0编辑  收藏  举报