2、题意:就是求凸包周长
3、总结:第一次做计算几何,没办法,还是看了大牛的博客
#include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #include<cstdlib> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define LL long long using namespace std; const int N=110,MAX=1000100; const double eps=1e-8; struct Point { double x,y; }p[N],stack[N]; int isZero(double x) { //x是否为0,还是不明白为什么要引入eps return (x>0?x:-x)<eps; } double crossProd(Point A,Point B,Point C) { //叉积,这样写即A->B到A->C逆时针为正 return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x); } double dis(Point A,Point B) { return sqrt((B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y)); } //以最左下的点为基准点,其他各点(逆时针方向)以极角从小到大的排序规则 int cmp(const void *a,const void *b) { //这里表示*a在*b后 Point *c=(Point *)a, *d=(Point *)b; double k=crossProd(p[1],*c,*d); //极角大小转化为求叉乘 if(k<eps||isZero(k)&&dis(p[1],*d)<dis(p[1],*c)) return 1; return -1; } int n; double Graham() { int mi=1; double mx=p[1].x, my=p[1].y; FF(i,2,n) { //找到最左下点 if(my>p[i].y||my==p[i].y&&mx>p[i].x) { mi=i, my=p[i].y, mx=p[i].x; } } p[0]=p[mi], p[mi]=p[1], p[1]=p[0]; //最左下点要换到p开头,不能让它和它自己比 qsort(p+2,n-1,sizeof(Point),cmp); stack[1]=p[1], stack[2]=p[2], stack[3]=p[3]; p[n+1]=p[1]; //在结尾加最左下点为结束点,一开始没加,直接在len加了一个dis(p[1],p[n]),这样忽略了很多 int top=3; for(int i=4; i<=n+1; i++) { //加入一个点后,向右偏拐或共线,则上一个点不在凸包内,则--top,该过程直到不向右偏拐或没有三点共线的点 while(crossProd(stack[top-1],stack[top],p[i])<eps&&top>=3) top--; stack[++top]=p[i]; } double len=0; F(i,1,top) { len+=dis(stack[i],stack[i+1]); } return len; } int main() { while(scanf("%d",&n)!=EOF,n) { FF(i,1,n) { scanf("%lf%lf",&p[i].x,&p[i].y); } if(n==1) printf("0.00 "); else if(n==2) printf("%.2lf ",dis(p[1],p[2])); else { printf("%.2lf ",Graham()); //这里printf用G++11竟然输出0 } } return 0; }