UVA - 11177 Fighting Against a Polygonal Monster

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18542

给一个凸包,和一个圆,圆心给定,是(0,0),半径不确定,凸包给定,保证圆心严格在凸包内,给一个R,问半径是多少使得圆和凸包公共面积为R

二分一下半径,浮点二分,控制下eps即可。然后就是判断圆和凸包求交。这是一种通用的方法,把凸包的每条边和圆心构建若干个三角形,求所有三角形和凸包的有向公共面积之和,就是答案了。

怎么求那个特殊三角形和圆的有向公共面积?分几种情况讨论,一个点是圆心,还有两个点p2,p3,都在圆内,一个在一个不在,两个都不在,跑一发线段与圆求交点什么的,就可以过了。需要写的函数有点多。

感受到计算几何和用java写工程很相似,指的是调用函数方面,就写好很多函数,可以实现很多功能,然后一个solve函数调用很多写好的函数来实现总功能,把小函数写好了,大函数写起来就很方便、简洁,而且很多时候名字都很长,java里很多名字不都很长么?

My code

//Hello. I'm Peter.
//#pragma comment(linker, "/STACK:102400000,102400000")
#define input freopen("/Users/peteryuanpan/Documents/mycode/peterpanpan/peterpanpan/data.txt","r",stdin)
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
#define peter cout<<"i am peter"<<endl
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define MAXN
#define N 2015
#define M
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const double eps=1e-9,pi=acos(-1.0);
double R;
inline int dcmp(double x){
    if(fabs(x)<eps) return 0;
    else if(x<0) return -1;
    else return 1;
}
struct Point{
    double x,y;
    Point(){};
    Point(double xx,double yy){
        x=xx,y=yy;
    }
};
typedef Point Vector;
Vector operator+(const Vector a,const Vector b){
    return Vector(a.x+b.x,a.y+b.y);
}
Vector operator-(const Vector a,const Vector b){
    return Vector(a.x-b.x,a.y-b.y);
}
double operator*(const Vector a,const Vector b){
    return a.x*b.x+a.y*b.y;
}
double operator%(const Vector a,const Vector b){
    return a.x*b.y-a.y*b.x;
}
Vector operator*(const Vector a,const double b){
    return Vector(a.x*b,a.y*b);
}
Vector operator*(const double b,const Vector a){
    return Vector(a.x*b,a.y*b);
}
bool operator==(const Vector a,const Vector b){
    return !dcmp(a.x-b.x)&&!dcmp(a.y-b.y);
}
double Length(Vector v){
    return sqrt(v.x*v.x+v.y*v.y);
}
double Square_Triangle(Point p1,Point p2,Point p3){
    return 0.5*fabs((p2-p1)%(p3-p1));
}
struct Circle{
    Point c;
    double r;
    Circle(){};
    Circle(Point cc,double rr){
        c=cc,r=rr;
    }
};
bool PointInCircle(Point p,Circle c){
    return dcmp(Length(p-c.c)-c.r)<=0;
}
bool PointOnSegment(Point p,Point p1,Point p2){
    return dcmp((p1-p)*(p2-p))<=0;
}
void SegmentIntersectCircle(Point p1,Point p2,Circle C,Point *res,int& numres){
    double a=(p1-C.c).x,b=(p2-p1).x,c=(p1-C.c).y,d=(p2-p1).y;
    double e=b*b+d*d,f=2*(a*b+c*d),g=a*a+c*c-C.r*C.r;
    double delta=f*f-4*e*g,t1,t2;
    int t=dcmp(delta);
    Point p;
    if(t<0) numres=0;
    else if(t==0){
        numres=0;
        t1=t2=(-f)/(2*e); p=p1+(p2-p1)*t1; if(PointOnSegment(p,p1,p2)) res[numres++]=p;
    }
    else{
        numres=0;
        t1=(-f-sqrt(delta))/(2*e); p=p1+(p2-p1)*t1; if(PointOnSegment(p,p1,p2)) res[numres++]=p;
        t2=(-f+sqrt(delta))/(2*e); p=p1+(p2-p1)*t2; if(PointOnSegment(p,p1,p2)) res[numres++]=p;
    }
}
double Angle(Vector v1,Vector v2){
    return acos((v1*v2)/Length(v1)/Length(v2));
}
double Square_fan(Circle c,Vector v1,Vector v2){
    double a=Angle(v1,v2);
    if(!dcmp(a-pi)) a=0.0;
    return c.r*c.r*a*0.5;
}
double CommonArea_TriangleWithCircle(Circle c,Point p1,Point p2,Point p3){
    bool p2in=PointInCircle(p2,c);
    bool p3in=PointInCircle(p3,c);
    int num=p2in+p3in,nump;
    Point res[5];
    if(num==2) return Square_Triangle(p1,p2,p3);
    if(num==1){
        if(p3in) swap(p2,p3);
        SegmentIntersectCircle(p3,p2,c,res,nump);
        return Square_fan(c,p3-p1,res[0]-p1)+Square_Triangle(p1,res[0],p2);
    }
    //num=0
    SegmentIntersectCircle(p3,p2,c,res,nump);
    if(nump==2) return Square_fan(c,p3-p1,res[0]-p1)+Square_Triangle(p1,res[0],res[1])+Square_fan(c,p2-p1,res[1]-p1);
    else return Square_fan(c,p2-p1,p3-p1);
}
double CommonArea_ConvexHullWithCircle(Circle c,Point *con,int numcon){
    double res=0.0;
    for(int i=0;i<numcon-1;i++){
        double s=CommonArea_TriangleWithCircle(c,c.c,con[i],con[i+1]);
        if(dcmp((con[i]-c.c)%(con[i+1]-c.c))>0) res+=s;
        else res-=s;
    }
    return fabs(res);
}
void Unique(Point *p,int &n){
    if(!n) return;
    int nt=n; n=1;
    for(int i=1;i<nt;i++){
        if(p[i]==p[i-1]) continue;
        p[n++]=p[i];
    }
}
Point p[N];
int n;
int main(){
    int kase=1;
    while(1){
        n=read();
        if(!n) break;
        scanf("%lf",&R);
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&p[i].x,&p[i].y);
        }
        Unique(p,n);
        p[n++]=p[0];
        double l=0.0,r=1e18,mid;
        while(dcmp(r-l)){
            mid=(l+r)*0.5;
            double s=CommonArea_ConvexHullWithCircle(Circle(Point(0,0),mid),p,n);
            if(dcmp(s-R)>=0) r=mid;
            else l=mid+eps;
        }
        printf("Case %d: %.2f\n",kase++,l);
    }
    return 0;
}

你可能感兴趣的:(计算几何,圆和多边形求交,浮点二分)