Ural-1020. Rope(簡單計算幾何)
阿新 • • 發佈:2019-01-24
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; const int N = 110; const double eps = 1e-8; const double PI = 3.1415926535898; struct point { double x,y; }s[N],t[N]; bool isZero(double x) { return (x>0?x:-x)<eps; } double dis(point a,point b)//兩點間的距離 { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } //向量ab和向量ac的叉積 double crossProd(point a,point b,point c) { return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); } //以最左下的點為基準點,其他各點(逆時針方向)以極角從小到大的排序規則 int cmp(const void * a,const void * b) { point *c = (point *)a; point *d = (point *)b; double k = crossProd(t[0],*c,*d); if(k<eps||(isZero(k) && (dis(t[0],*c)>dis(t[0],*d)))) return 1; return -1; } double Graham(int n) { double x = t[0].x; double y = t[0].y; int k = 0; for (int i=1; i<n; ++i) {//找到最左下的一個點 if (t[i].x<x || (t[i].x==x && t[i].y<y)) { x = t[i].x; y = t[i].y; k = i; } } //交換,將最左的點移至陣列首位 point tmp = t[k]; t[k] = t[0]; t[0] = tmp; qsort(t+1, n-1, sizeof(point), cmp); // sort(t+1,n-1,cmp); t[n] = t[0]; s[0] = t[0]; s[1] = t[1]; s[2] = t[2]; int top = 2; for (int i=3; i<=n; ++i) {//加入一個點後,向右偏拐或共線,則上一個點不在凸包內,則--top,該過程直到不向右偏拐或沒有三點共線的點 while (crossProd(s[top-1], s[top], t[i])<=eps && top>=2) --top; s[++top] = t[i];//在當前情況下符合凸包的點,入棧 } double len = 0; for (int i=0; i<top; ++i) len += dis(s[i], s[i+1]); return len; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int n; double r; scanf("%d%lf",&n,&r); for(int i=0;i<n;i++) { scanf("%lf%lf",&t[i].x,&t[i].y); } if(n==1) { printf("%.2lf\n",2*PI*r); } else if(n==2) { printf("%.2lf\n",2*(PI*r+dis(t[0],t[1]))); } else { printf("%.2lf\n",Graham(n)+2*PI*r); } return 0; }