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;
}
时间: 2024-11-03 21:48:11

UVA - 11177 Fighting Against a Polygonal Monster的相关文章

uva 11177(凸多边形和圆的相交)

题意:按顺时针或逆时针顺序给出一个凸n边形的n个点的坐标,然后让一个圆心在(0,0)的圆和凸n边形相交的面积大于等于R,问圆的最小半径. 题解:这题简直坑爹啊,各种细节错误..修修改改了一天,最后看别人题解也还是不懂为什么OnSegment函数要写成那样...明明不能判断点是否在线段上 ╮(╯▽╰)╭ 画画图思路不难想到,把凸n边形的每条边都和圆判断关系,如果是边的两点都在圆内,两条边对应一个三角形的面积,如果一个点在圆外一个在圆内(包括边界),那就是一个三角形加一个扇形,如果两点都在圆外,分两

uva 1318 - Monster Trap(bfs+暴力)

题目链接:uva 1318 - Monster Trap 每条线段2个点,加上起点终点一个是202个点,暴力判断连点之间是否可达,可达建边.因为线段有厚度考虑,所以将线段延伸一点再处理,这样原本共用一端点的线段变成相交.特殊情况是三点共线,这是判断延伸后的点是否落在其他线段上,如果是就不考虑这个点.最后做一遍bfs. #include <cstdio> #include <cstring> #include <cmath> #include <vector>

uva 11595 - Crossing Streets EXTREME(切割多边形)

题目链接:uva 11595 - Crossing Streets EXTREME 对初始平面进行切割,得到所有平面,然后处理出所有边,有公共边的两个平面之间可以到达,对于城市的权值可以加到点上,进出各加一次即可. #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <vector> #include <complex> #in

uva 6757 Cup of Cowards(中途相遇法,貌似)

uva 6757 Cup of CowardsCup of Cowards (CoC) is a role playing game that has 5 di?erent characters (Mage, Tank, Fighter,Assassin and Marksman). A team consists of 5 players (one from each kind) and the goal is to kill amonster with L life points. The

uva live 4123 Glenbow Museum 数学递推

// uva live 4123 Glenbow Museum 数学递推 // // 题目大意: // // 对于一个边平行于坐标轴的多边形,我们可以用一个序列来描述,R和O,R表示 // 该顶点的角度为90度,O表示该定点的角度为270.给定序列的长度.问能由这些RO序 // 列组成的星型多边形(内部存在一个点可以看到所有的节点的多边形)的方法数有多少. // // 解题思路: // // 顶点数一定是序列的长度.n小于4无法组成多边形.n为奇数的时候也不行.设R的个数有 // x个,O的个数

uva 11361 Investigating Div-Sum Property 数位dp

// uva 11361 Investigating Div-Sum Property 数位dp // // 题目大意: // // 给你一个整数a和一个整数b,问在[a,b]范围内,有多少个自身被k整除并且 // 各位数之和也能被k整除.比如k = 7 ,322满足条件,因为332能被整除7,并 // 3 + 2 + 2 = 7 也能被7整除 // // 解题思路: // // 求一个区间的题目,这类题目,往往可以转化为不超过x的f(x).则最后要求 // 的就是f(b) - f(a-1).如

uva 10065 (凸包+求面积)

链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=1006 Problem A Useless Tile Packers Input: standard input Output: standard output Yes, as you have apprehended the Useless Tile Pac

uva 562 Dividing coins

Dividing coins It's commonly known that the Dutch have invented copper-wire. Two Dutch men were fighting over a nickel, which was made of copper. They were both so eager to get it and the fighting was so fierce, they stretched the coin to great lengt

UVA 11795

B Mega Man's Missions Input Standard Input Output Standard Output Mega Man is off to save the world again. His objective is to kill the Robots created by Dr. Wily whose motive is to conquer the world. In each mission, he will try to destroy a particu