HD 1392 Surround the Trees 解题报告

来源:互联网 发布:无锡软件开发 编辑:程序博客网 时间:2024/06/02 00:02

Surround the Trees

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6231 Accepted Submission(s): 2339


Problem Description
There are a lot of trees in an area. A peasant wants to buy a rope to surround all these trees. So at first he must know the minimal required length of the rope. However, he does not know how to calculate it. Can you help him?
The diameter and length of the trees are omitted, which means a tree can be seen as a point. The thickness of the rope is also omitted which means a rope can be seen as a line.



There are no more than 100 trees.

Input
The input contains one or more data sets. At first line of each input data set is number of trees in this data set, it is followed by series of coordinates of the trees. Each coordinate is a positive integer pair, and each integer is less than 32767. Each pair is separated by blank.

Zero at line for number of trees terminates the input for your program.

Output
The minimal length of the rope. The precision should be 10^-2.

Sample Input
9 12 7 24 9 30 5 41 9 80 7 50 87 22 9 45 1 50 7 0

Sample Output
243.06
解题分析:
此题为典型的求凸包问题,题意为,此地有n棵树,农场主要用最短的绳子围住所有树,让你计算最少需要绳子的长度。题目要注意只有一个点的情况,还有只有两个点的情况。
解题代码:
#include <iostream>#include <cmath>#include <algorithm>#include <stdio.h>/***这是一个求凸包的模板***/using namespace std;const int MAXN = 100;const double eps = 1e-8;struct Point{    int x;    int y;};struct Point p[MAXN]; // 保存输入结点struct Point st[MAXN];  // 保存凸包结点,把que当一个栈来使用int top;          // 记录栈顶位置double dis(Point a, Point b)// 求a, b两点距离{    return sqrt(double((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)));}int cross(Point p1,Point p2, Point p0)// 求P0P1与P0P2的叉积{    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}bool cmp(Point p1,Point p2){    int k = cross(p2,p1,p[0]); //p0p2叉乘p0p1    if(k<0||(!k&&dis(p1,p[0])-dis(p2,p[0])>eps))//p1的极角比p2小或者极角相等去距离大的        return true;    else  return false;}void GrahamScan(int n){    Point tmp;    int k = 0;    for(int i=1; i<n; ++i)//找出y值(y值相同时找x最小)最小的点作为起始点P0        if((p[i].y < p[k].y) || ((p[i].y==p[k].y) && (p[i].x<p[k].x)))            k = i;    tmp = p[0];    p[0] = p[k];    p[k] = tmp;    sort(p+1,p+n,cmp);// 按极角大小排序    top = -1;    st[++top] = p[0];    st[++top] = p[1];    st[++top] = p[2];  //先把极角最小的0, 1, 2三点存入栈中    for(int i=3; i<n; ++i) //从第3点开始,直到最后,如果不能左转,则退栈.    {        while((cross(p[i], st[top],st[top-1]))>=0)    //如果不能左转,则退栈            top--;        st[++top]=p[i];    }    ++top;}/***********************************************/int main(){    int n,i;    double s_dist;    while(scanf("%d",&n)!=EOF)    {        if(n==0)            break;        else        {            for(i=0; i<n; i++)                scanf("%d%d",&p[i].x,&p[i].y);            if(n==1)//如果只有一个点                printf("0\n");            else if (n==2)//如果有两个点                printf("%.2lf\n",dis(p[0],p[1]));            else            {                GrahamScan(n);                s_dist=dis(st[0],st[top-1]);                for(i=0; i<top-1; i++)                    s_dist=s_dist+dis(st[i],st[i+1]);                printf("%.2lf\n",s_dist);            }        }    }    return 0;}



原创粉丝点击