C题Dogs'House 求凸包上的点

来源:互联网 发布:沈阳盘古网络工资 编辑:程序博客网 时间:2024/04/27 02:42

C-Dogs' House

Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 134   Accepted Submission(s) : 45

Font: Times New Roman | Verdana | Georgia

Font Size:  

Problem Description

George wishes to build a House to contain his dogs(without roof), but he's a bit short on cash right. Any Wall he builds must contain all of the favorite grazing spots for his dogs. Given the location of these spots, determine the length of the shortest Wall which encloses them.

Input

There are several test cases.
In each test case:
The first line of the input file contains one integer, N. N (0 <= N <= 10,000) is the number of grazing spots that George wishes to enclose. The next N line consists of two real numbers, Xi and Yi, corresp
onding to the location of the grazing spots in the plane (-1,000,000 <= Xi,Yi <= 1,000,000). The numbers will be in decimal format.

Output

The output should consist of one real number, the length of fence required. The output should be accurate to two decimal places.

Sample Input

44 84 125 9.37 8

Sample Output

12.00

Author

hnfnu

给出一系列的点 围城一个凸多边形,使其包括所有的点,求这个凸多边形的周长。

采用的是思路比较简单的卷包裹法

先找出所有点中最左边的点,然后求最左边上的点与图中每一个点的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);    }}