HDU 1348 wall (简单凸包)

http://acm.hdu.edu.cn/showproblem.php?pid=1348

这题是在求凸包的基础上,再求每个顶点对应角度及半径的弧长,外面围墙的直线部分与城墙的凸包长相同;再求弧长总和,注意每段弧长对应的角与凸包顶点的夹角是一样的,所以,又因为每个顶对应的半径长都是l,所以一个多边形的所顶点对应弧长相加其实就是一个圆。

所以,最后总长为 凸包边长+2*3.141592653*l(l为已知与城堡的最远距离)

#include<stdio.h>
#include<math.h>
#define PI 3.141592653
struct node
{
  double x,y;
}p[11000];
int hash[11000];
double distance(int a,int b)//求两点之间距离
{
    return sqrt(pow(p[a].x-p[b].x,2)+pow(p[a].y-p[b].y,2));
}
int cross_product(int a,int b,int c)//求两向量叉乘
{
    double x1,y1,x2,y2;
    x1=p[a].x-p[c].x;
    y1=p[a].y-p[c].y;
    x2=p[b].x-p[c].x;
    y2=p[b].y-p[c].y;
    if(x1*y2-x2*y1>0)
        return a;
    if(fabs(x1*y2-x2*y1)<1e-6)
    {
        if(distance(a,c)>distance(b,c))return a;
        else return b;
    }
    return b;
}
int main()
{
    int n,i,p0,j,pj,pi,t;
    double x0,y0,sum,l;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%lf",&n,&l);
        sum=0;
        x0=y0=999999;
        for(i=0;i<n;i++)
        {
            hash[i]=0;
            scanf("%lf%lf",&p[i].x,&p[i].y);
            if(p[i].y<y0||(p[i].y==y0&&p[i].x<x0))
            {
                x0=p[i].x;
                y0=p[i].y;
                p0=i;
            }
        }
            pi=p0;
        for(i=0;i<n;i++)
        {
            pj=p0;
            for(j=0;j<n;j++)
            {
                  pj=cross_product(j,pj,pi);
            }
            hash[pj]=1;
            sum=sum+distance(pi,pj);
            pi=pj;
            if(pj==p0)break;
        }
        sum+=2.0*l*PI;
        sum=(sum*10+5)/10;
        printf("%d\n",(int)sum);
        if(t)printf("\n");
    }
    return 0;
}
View Code

 

posted @ 2013-08-21 17:13  执着追求的IT小小鸟  阅读(243)  评论(0编辑  收藏  举报