您的位置:首页 > Web前端

Fencing the Cows [USACO]

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

/*
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: