天天写算法之Surround the Trees

这个题目还是利用了chaji的思想,小于0,则顺时针,大于零则逆时针。

代码如下:

#include<iostream>
#include<string.h>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define MAX 105

using namespace std;

struct point{
    double x ;
    double y ;
    friend operator == (point a , point b)
    {
        if(a.x==b.x&&a.y==b.y)
            return true ;
        return false ;
    }
}points[MAX];
int n ;
bool cmp(point a , point b )
{
    if(a.y==b.y)
        return a.x<b.x;
    return a.y<b.y;
}
double judge(point a, point b , point base )
{
     return (a.x - base.x)*(b.y-base.y)-(b.x-base.x)*(a.y-base.y);
}
double dis(point a,point b )
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double bk(int n)
{
    if(n==1)
        return 0 ;
    if(n==2)
        return dis(points[1],points[2]);
    int ans[MAX];
    ans[1]=1 ;
    int index= 1;
    //当它第一次转回来的时候中止
    //主要思想是,每次都找到一个相对于上次的线最左侧的点,在这个点的基础上,随意再选一个点,看是否存在比这个点更加偏向右的点,这样就不必分两种情况了。
    do{
        index++;
        int t = ans[index-1]+1;//找到上一次解决的点,+1得到下一个点
        if(t>n)
            t = 1 ;//注意这个地方,其实把最后的点也算了进去,也就是围城了一个圈,当把最后一个点算进去的时候才中止
    
        for(int i = 1 ; i<= n ; i ++)
        {
            if(judge(points[i],points[t],points[ans[index-1]])<0)
            {
                t = i ;
            }
        }//这个地方还很巧妙的把共线的情况也算了进去,很厉害,如果共线,那么上面的if肯定进不去,就会在上一个的基础上把t原封不懂得传递过来
        ans[index]=t;
    }while(ans[index]!=ans[1]);

    double res = 0;
    for(int i = 1 ; i < index ;i++)
    {

        res +=dis(points[ans[i]],points[ans[i+1]]);
    }
    return res ;
}

int main(){
    int i, j ;
    while(scanf("%d",&n),n)
    {
        for(i = 1 ; i <= n ; i ++)
        {
            scanf("%lf%lf",&points[i].x,&points[i].y);
        }
        sort(points+1,points+1+n,cmp);
        printf("%.2lf\n",bk(n));
    }
}

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页