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; }