hdu 4667(凸包)

来源:互联网 发布:日文手写输入在线软件 编辑:程序博客网 时间:2024/06/06 04:42

题意:给出n个圆和m个三角形,把所有的图形围起来的最小长度。

分析:本题正解是求一堆切线,但是本题数据水,所以,把圆分成1000个点求凸包就好了,但是求长度的时候,在圆上的点要求圆弧长度。

代码如下:

<span style="font-family:FangSong_GB2312;font-size:18px;">#include <map>#include <set>#include <vector>#include <math.h>#include <string>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>#include <functional>using namespace std;const int MAXN=100005;const double eps=1e-10;const double pi=acos(-1.0);int dcmp(double x){    if(fabs(x)<eps)return 0;    if(x>0)return 1;    return -1;}                                                   //因为精度的问题,在这里求减法的精度struct Point {    double x,y;    int id;                                        //所在的图形}p[MAXN];                                          //几何图形中的点集double dot(Point a,Point b,Point c){    double s1=b.x-a.x;    double t1=b.y-a.y;    double s2=c.x-a.x;    double t2=c.y-a.y;    return s1*s2+t1*t2;}                                                 //求解点积int n,res[MAXN],top;bool cmp(Point a,Point b){    if(a.y==b.y)return a.x<b.x;    return a.y<b.y;}                                                  //凸包的排序bool mult(Point sp,Point ep,Point op){    return (sp.x-op.x)*(ep.y-op.y)>=(ep.x-op.x)*(sp.y-op.y);}                                                  //凸包中的判断void Graham(){    int len;    top=1;    sort(p,p+n,cmp);    if(n==0)return;res[0]=0;    if(n==1)return;res[1]=1;    if(n==2)return;res[2]=2;    for(int i=2;i<n;i++){        while(top&&mult(p[i],p[res[top]],p[res[top-1]]))top--;        res[++top]=i;    }    len=top;    res[++top]=n-2;    for(int i=n-3;i>=0;i--){        while(top!=len&&mult(p[i],p[res[top]],p[res[top-1]]))top--;        res[++top]=i;    }}                                                    //求解凸包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 R[1000];int main(){    int x,m;    while(scanf("%d%d",&x,&m)!=EOF){        n=0;        double x1,y1,r;        for(int i=0;i<x;i++){            scanf("%lf%lf%lf",&x1,&y1,&r);            R[i]=r;            for(int j=0;j<1000;j++){                double tmp=2*pi*j/1000;            //分解圆                p[n].id=i;                p[n].x=x1+r*cos(tmp);                p[n++].y=y1+r*sin(tmp);            }        }        while(m--){            for(int i=1;i<=6;i++){                scanf("%lf",&r);                if(i&1)p[n].x=r;                else{                    p[n].id=n;                    p[n++].y=r;                }            }        }        Graham();        double ans=0;        for(int i=0;i<top;i++){            int t1=p[res[i]].id;            int t2=p[res[(i+1)%top]].id;            if(t1==t2){                ans+=pi*2*R[t1]/1000;            }            else ans+=dis(p[res[i]],p[res[(i+1)%top]]);        //求和        }        printf("%.4lf\n",ans);    }    return 0;}</span>

0 0
原创粉丝点击