Fighting Against a Polygonal Monster - UVa 11177 圆和凸包面积的交

39 篇文章 0 订阅

题意:给你一个凸包,求圆的最小半径使得面积的并>R。

思路:二分这个半径,然后就是纯几何模板了,不知道为什么long double 就能过,double就会WA。反正UVa经常会出现神奇的现象,我表示已经习惯了。

AC代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
struct Point
{
    long double x,y;
    Point(long double x=0,long double y=0):x(x),y(y){}
};
typedef Point Vector;
long double PI=acos(-1.0),eps=1e-10;
Vector operator + (Point A,Point B){return Point(A.x+B.x,A.y+B.y);}
Vector operator - (Point A,Point B){return Point(A.x-B.x,A.y-B.y);}
Point operator * (Point A,long double p){return Point(A.x*p,A.y*p);}
int dcmp(double x){return (x>eps)-(x<-eps);}
bool operator == (const Point &A,const Point &B){return dcmp(A.x-B.x)==0 && dcmp(A.y-B.y)==0;}
long double Dot(Vector A,Vector B){return A.x*B.x+A.y*B.y;}
long double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
long double Length(Vector A){return sqrt(Dot(A,A));}
long double Angle(Vector A,Vector B){return acos(Dot(A,B)/Length(A)/Length(B));}
Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)
{
    Vector u=P-Q;
    long double t=Cross(w,u)/Cross(v,w);
    return P+v*t;
}
long double DistanceToLine(Point P,Point A,Point B)
{
    Vector v1=B-A,v2=P-A;
    return fabs(Cross(v1,v2)/Length(v1));
}
Point GetLineProjection(Point P,Point A,Point B)
{
    Vector v=B-A;
    return A+v*(Dot(v,P-A)/Dot(v,v));
}
bool OnSegment(Point P,Point A,Point B){return dcmp(Cross(A-P,B-P))==0 && dcmp(Dot(A-P,B-P))<=0;}
Point Zero(0,0);
struct Circle
{
    Point c;
    double r;
    Circle(Point c=Zero,long double r=0):c(c),r(r){}
    Point point(long double a){return Point(c.x+r*cos(a),c.y+r*sin(a));}
};
struct Line
{
    Point p;
    Vector v;
    Line(Point p=Zero,Vector v=Vector(0,1)):p(p),v(v){}
    Point point(long double t){return Point(p+v*t);}
};
int GetLineCircleIntersection(Line L,Circle C,long double &t1,long double &t2,vector<Point> &sol)
{
    long double a=L.v.x;
    long double b=L.p.x-C.c.x;
    long double c=L.v.y;
    long double d=L.p.y-C.c.y;
    long double e=a*a+c*c;
    long double f=2*(a*b+c*d);
    long double g=b*b+d*d-C.r*C.r;
    long double delta=f*f-4*e*g;

    if(dcmp(delta)<0)
      return 0;
    if(dcmp(delta)==0)
    {
        t1=t2=-f/(2*e);
        sol.push_back(L.point(t1));
        return 1;
    }
    else
    {
        t1=(-f-sqrt(delta))/(2*e);
        t2=(-f+sqrt(delta))/(2*e);
        sol.push_back(L.point(t1));
        sol.push_back(L.point(t2));
        return 2;
    }
}
long double common_area(Circle C,Point A,Point B)
{
    if(A==C.c || B==C.c)
      return 0;
    long double OA=Length(A-C.c),OB=Length(B-C.c);
    long double d=DistanceToLine(Zero,A,B);
    int sg=dcmp(Cross(A,B));
    if(sg==0)
      return 0;
    long double angle=Angle(A,B);
    if(dcmp(OA-C.r)<=0 && dcmp(OB-C.r)<=0)
      return Cross(A,B)/2;
    if(dcmp(OA-C.r)>=0 && dcmp(OB-C.r)>=0 && dcmp(d-C.r)>=0)
      return sg*C.r*C.r*angle/2;
    if(dcmp(OA-C.r>=0 && dcmp(OB-C.r)>=0 && dcmp(d-C.r)<0))
    {
        Point prj=GetLineProjection(Zero,A,B);
        if(OnSegment(prj,A,B))
        {
            vector<Point> p;
            Line L=Line(A,B-A);
            long double t1,t2;
            GetLineCircleIntersection(L,C,t1,t2,p);
            long double s1=C.r*C.r*angle/2;
            long double s2=C.r*C.r*Angle(p[0],p[1])/2;
            s2-=fabs(Cross(p[0],p[1])/2);
            s1-=s2;
            return sg*s1;
        }
        else
          return sg*C.r*C.r*angle/2;
    }
    else
    {
        if(dcmp(OB-C.r)<0)
        {
            Point temp=A;
            A=B;
            B=temp;
        }
        Point inter_point;
        long double t1,t2;
        Line L=Line(A,B-A);
        vector<Point> inter;
        GetLineCircleIntersection(L,C,t1,t2,inter);
        if(OnSegment(inter[0],A,B))
          inter_point=inter[0];
        else
          inter_point=inter[1];
        long double s=fabs(Cross(inter_point,A)/2);
        s+=C.r*C.r*Angle(inter_point,B)/2;
        return s*sg;
    }
}
Point p[60];
int n,t;
long double R;
int main()
{
    int i,j,k;
    long double l,r,mi,ans;
    while(~scanf("%d",&n) && n>0)
    {
        scanf("%Lf",&R);
        for(i=0;i<n;i++)
           scanf("%Lf%Lf",&p[i].x,&p[i].y);
        p[n]=p[0];
        l=0;r=1e10;
        while(r-l>1e-6)
        {
            mi=(l+r)/2;
            Circle C(Zero,mi);
            ans=0;
            for(i=0;i<n;i++)
               ans+=common_area(C,p[i],p[i+1]);
            if(fabs(ans)>=R)
              r=mi;
            else
              l=mi;
        }
        printf("Case %d: %.2Lf\n",++t,mi);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
geometric modeling based on polygonal meshes (基于多边形网格的几何建模)是一种常用的三维建模方法,主要用于创建、编辑和操作多边形网格模型。该方法使用一系列的顶点、边和面来描述物体的几何结构。 这种建模方法的代码实现包括以下几个关键步骤。首先,通过读取或创建输入的多边形网格数据,包括顶点坐标和面的连接信息。接下来,进行模型的编辑和操作,比如移动顶点、调整边和面,或者添加删除顶点、边和面。在编辑过程中,还可以进行细分、合并、镜像、变形等操作,以获得更复杂的几何形状。 在编辑完成后,多边形网格模型可以进行进一步的处理和优化。例如,进行曲面重建以得到光滑的几何表面,进行材质和纹理的贴图,或者进行拓扑结构优化以减少模型的面数和存储空间。 在代码实现中,需要使用适当的数据结构来表示多边形网格,比如使用数组、链表或树等方式存储顶点、边和面的信息。同时,还需要实现各种编辑和操作的算法,如移动、旋转、缩放等,以及模型处理和优化的算法。 此外,为了提高建模效率和减少计算复杂度,可以使用一些优化技术,如边缘塌陷、局部细分、空间划分等,来提高代码性能和减少内存占用。 综上所述,geometric modeling based on polygonal meshes的代码实现涉及了多个关键步骤和算法,以实现对三维模型的创建、编辑和优化。这种方法在计算机图形学、虚拟现实、游戏开发等领域得到广泛应用,为我们提供了强大而灵活的三维形状建模工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值