4 4 8 4 12 5 9.3 7 8
12.00
给出一系列的点 围城一个凸多边形,使其包括所有的点,求这个凸多边形的周长。
采用的是思路比较简单的卷包裹法
先找出所有点中最左边的点,然后求最左边上的点与图中每一个点的sin值,将sin值按从小到大的顺序排放,如果点是从0位置开始排序的话,那么0,1必是凸包上面的点,一遍从最左边扫到最右边,求cross(叉积)值,确定每条边所拐的方向是否为同一个方向,(用stl函数库定义两个栈,一个存放向量,另一个存放点,)如果是一个方向,向量和点进栈,如果不是一个方向,向量和点出栈 。 求得向量栈中的所有向量的长度,这里包括起始点和终点所连的向量。
#include<stdio.h> #include<iostream> #include<algorithm> #include<math.h> #include<stack> struct stu { //定义了两个向量 double x,y; }vec[2]; struct node{ //定义了每个点的四种属性 角度,两点距离,横纵坐标 double x,y,sinangle,dis; }point[20000]; int cmp(node a,node b) //比较函数 快排的比较函数确定最左边的坐标 { if(b.x-a.x>0)return 1; else return 0; } int cmp1(node a,node b)//按sinangle的角度大小 从小到大进行排序 { if(b.sinangle-a.sinangle>0) return 1; else return 0; } double judge(stu a,stu b)// 向量的叉积 { if( a.x*b.y-a.y*b.x>0)return 100; else return -100; } double distant(node a,node b) { return sqrt( (b.y-a.y)*(b.y-a.y)+(b.x-a.x)*(b.x-a.x) ); } double value(stu a) { return sqrt( a.x*a.x+a.y*a.y ); } const double min=0.0000001; //定义了最小值 using namespace std; stack <struct stu> my; stack <struct node> doc; int main() { int n,i; node j; stu num; double sum=0; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;i++) //输入n组数据 scanf("%lf %lf",&point[i].x,&point[i].y); sort(point,point+n,cmp); //对其进行排序找出最左边的值 //输出所有数据 // for(i=0;i<n;i++) // printf("%lf %lf\n",point[i].x,point[i].y); //找出最小值 // printf("min x %lf %lf",point[0].x,point[0].y); for(i=1;i<n;i++) { point[i].dis=distant(point[0],point[i]); point[i].sinangle=(point[i].y-point[0].y)/point[i].dis; // printf("point[%d].sinangle=%lf\n",i,point[i].sinangle); } // printf("\n"); sort(point+1,point+n,cmp1);//按角度进行排序(从小到大) //输出从1-n-1的sinangle值 // for(i=1;i<n;i++) // printf("point[%d].sinangle=%lf\n",i,point[i].sinangle); // printf("!!!!!!!!!!!!!!!\n"); vec[0].x=point[1].x-point[0].x; //第一条边一定产生是凸包的一条边 vec[0].y=point[1].y-point[0].y; while(!my.empty()) my.pop(); //my栈中存放的是向量的值 my.push(vec[0]); //将栈中原来的所有点释放 while(!doc.empty()) //doc栈中存放的点 doc.pop(); doc.push(point[0]); //0,1两个点必在凸包中。 doc.push(point[1]); point[n]=point[0]; //将point[0]赋给point[n]形成一个循环 for(i=2;i<=n;i++) { //printf("i=%d\n",i); vec[0]=my.top(); j=doc.top(); vec[1].x=point[i].x-j.x; //反复使用vec[0],vec[1]生成向量 vec[1].y=point[i].y-j.y; if(judge(vec[0],vec[1])>0){ //如果旋转方向相同 点和向量进栈 doc.push(point[i]); my.push(vec[1]); } else {my.pop();doc.pop();i--;} //如果不相同,则点和向量出栈 } sum=0; while(!my.empty()) { num=my.top(); my.pop(); sum+=value(num); } printf("%.2lf\n",sum); } }