就是跟大白279页的题有点类似的模版题而已。
#include"bits/stdc++.h"
using namespace std;
const int MX = 207;
const double eps = 1e-12;
int n;
struct Point {
double x, y;
Point() {}
Point(double x,double y):x(x),y(y) {}
void read(){
scanf("%lf %lf",&x,&y);
}
void print(){
printf("%.12f %.12f\n",x,y);
}
}po[MX];
Point v[MX],v2[MX];
typedef Point Vector;
int dcmp(double x) { //返回x的正负
if(fabs(x)<eps)return 0;
return x<0?-1:1;
}
Vector operator-(Vector A,Vector B) {return Vector(A.x - B.x, A.y - B.y);}
Vector operator+(Vector A,Vector B) {return Vector(A.x + B.x, A.y + B.y);}
Vector operator*(Vector A,double p) {return Vector(A.x*p, A.y*p);}
Vector operator/(Vector A,double p) {return Vector(A.x/p, A.y/p);}
bool operator<(const Point&a,const Point&b) {return a.x<b.x||(a.x==b.x&&a.y<b.y);}
bool operator==(const Point&a,const Point&b) {return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;}
double Dot(Vector A,Vector B) { //点积
return A.x*B.x+A.y*B.y;//如果改成整形记得加LL
}
double Cross(Vector A,Vector B) { //叉积
return A.x*B.y-A.y*B.x;//如果改成整形记得加LL
}
//向量长度
double Length(Vector A) {
return sqrt(Dot(A,A));
}
//2个向量之间的夹角
double Angle(Vector A,Vector B) {
return acos(Dot(A,B)/Length(A)/Length(B));
}
//向量的极角
double angle(Vector v) {
return atan2(v.y,v.x);
}
//计算ABC的有向面积
double Area(Point A,Point B,Point C) {
return Cross(B-A,C-A)/2;
}
//将A向量逆时针旋转rad
Vector Rotate( Vector A,double rad) {
return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
//返回A的逆时针旋转90度的单位法向量
Vector Normal(Vector A) {
double L=Length(A);
return Vector(-A.y/L,A.x/L);
}
//有向线段
struct Line {
Point p;
Vector v;//方向向量,左边为半平面
double ang;//极角
Line() {}
Line(Point p,Vector v):p(p),v(v) {
ang=atan2(v.y,v.x);
}
bool operator<(const Line &L)const { //极角排序
return ang<L.ang;
}
Point point(double t) {
return p + v*t;
}
Line move(double d) { //向左边平移d单位
return Line(p + Normal(v)*d, v);
}
}li[MX];
//计算2条直线P+tv和Q+tw的交点,请先确保不是平行(v!=w)
Point GetLineIntersection(const Line& a, const Line& b)
{
Vector u = a.p-b.p;
double t = Cross(b.v, u) / Cross(a.v, b.v);
return a.p+a.v*t;
}
bool OnLeft(const Line& L, const Point& p){
return dcmp(Cross(L.v, p-L.p)) > 0;
}
// 半平面交主过程
//返回交平面点数
int HalfplaneIntersection(Line *L,int n,Point *ans){
sort(L, L+n); // 按极角排序
int first, last; // 双端队列的第一个元素和最后一个元素的下标
Point p[n]; // p[i]为q[i]和q[i+1]的交点
Line q[n]; // 双端队列
q[first=last=0] = L[0]; // 双端队列初始化为只有一个半平面L[0]
for(int i = 1; i < n; i++){
while(first < last && !OnLeft(L[i], p[last-1])) last--;
while(first < last && !OnLeft(L[i], p[first])) first++;
q[++last] = L[i];
if(dcmp(Cross(q[last].v, q[last-1].v))==0) { // 两向量平行且同向,取内侧的一个
last--;
if(OnLeft(q[last], L[i].p)) q[last] = L[i];
}
if(first < last) p[last-1] = GetLineIntersection(q[last-1], q[last]);
}
while(first < last && !OnLeft(q[first], p[last-1])) last--; // 删除无用平面
if(last - first <= 1) return 0; // 空集
p[last] = GetLineIntersection(q[last], q[first]); // 计算首尾两个半平面的交点
// 从deque复制到输出中
for(int i = first; i <= last; i++) ans[i-first]=p[i];
return last-first+1;
}
struct Circle {
Point c;
double r;
Circle() {}
Circle(Point c,double r):c(c),r(r) {}
Point getpoint(double rad) {
return Point(c.x+cos(rad)*r,c.y+sin(rad)*r);
}
};
int GetCircleCircleIntersection(Circle C1, Circle C2, vector<Point>& sol) {
double d = Length(C1.c - C2.c);
if(dcmp(d) == 0) {
if(dcmp(C1.r - C2.r) == 0) return -1; // 重合,无穷多交点
return 0;
}
if(dcmp(C1.r + C2.r - d) < 0) return 0;//相离
if(dcmp(fabs(C1.r-C2.r) - d) > 0) return 0;//内含
double a = angle(C2.c - C1.c);
double da = acos((C1.r*C1.r + d*d - C2.r*C2.r) / (2*C1.r*d));
Point p1 = C1.getpoint(a-da), p2 = C1.getpoint(a+da);
sol.push_back(p1);
if(p1 == p2) return 1;//相切
sol.push_back(p2);//相交
return 2;
}
bool check(double r, Point &p1, Point &p2)
{
Point ploy[MX];
for(int i = 0; i < n; i++){
li[i] = Line(po[i]+v2[i]*r, v[i]);
}
int num = HalfplaneIntersection(li,n,ploy);
vector<Point>sol;
for(int i = 0; i < num; i++){
for(int j = i+1; j < num; j++){
if(GetCircleCircleIntersection(Circle(ploy[i],r),Circle(ploy[j],r),sol) == 0){
p1 = ploy[i];
p2 = ploy[j];
return 1;
}
}
}
return 0;
}
int main()
{
#ifdef LOCAL
freopen("input.txt","r",stdin);
#else
freopen("kabbalah.in","r",stdin);
freopen("kabbalah.out","w",stdout);
#endif // LOCAL
while(~scanf("%d",&n) && n){
for(int i = 0; i < n; i++){
po[i].read();
}
po[n] = po[0];
for(int i = 0; i < n; i++){
v[i] = po[i+1]-po[i];
v2[i] = Normal(v[i]);
}
double l = 0, r = 1e5;
Point p1,p2;
for(int cnt = 0; cnt <= 70; cnt++){
double mid = (l+r)*0.5;
if(check(mid,p1,p2)) l = mid;
else r = mid;
}
printf("%.12f\n",l);
p1.print();
p2.print();
}
return 0;
}