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