LA3890
题解
- 相当于求岛上半径最大的圆。
- 二分枚举半径r。把每一条边向里面平移r,如果存在这样的圆,那么平移后的存在半平面交。
代码
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
int const N = 100 + 10;
int n;
int dcmp(double x){ //判断符号
if(fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
typedef struct Point{ //点和向量
double x,y;
Point(){};
Point(double x,double y):x(x),y(y){};
Point operator + (const Point& e)const{ //加
return Point(x + e.x,y + e.y);
}
Point operator - (const Point& e)const{ //减
return Point(x - e.x,y - e.y);
}
Point operator * (const double e)const{ //乘
return Point(x * e,y * e);
}
}Vector;
double Dot(Vector a,Vector b){
return a.x * b.x + a.y * b.y;
}
double Cross(Vector a,Vector b){
return a.x * b.y - a.y * b.x;
}
Point a[N],t[N];
Vector to[N]; //单位法向量
struct Line
{
Point a,b;
double ang;
void getang(){ ang = atan2(b.y - a.y,b.x - a.x);}
bool operator == (const Line& e)const{
return !dcmp(ang - e.ang);
}
bool operator < (const Line& e)const{
return ang < e.ang || !dcmp(ang - e.ang) && dcmp(Cross(b - a,e.b - a)) < 0;
}
}poly[N],s[N],q[N];
bool onright(Point a,Point b,Point p){
return dcmp(Cross(b - a,p - a)) < 0;
}
Point intersection(Point p,Point v,Point q,Point w){
Point u = p - q;
double t = Cross(w,u) / Cross(v,w);
return p + v * t;
}
bool halfplaneintersection(){
for(int i=0;i<n;i++) s[i].getang();
sort(s,s+n);
int l,r;
q[l = r = 0] = s[0];
for(int i=1;i<n;i++){
if(s[i] == s[i-1]) continue;
while(l < r && onright(s[i].a,s[i].b,t[r-1])) r--;
while(l < r && onright(s[i].a,s[i].b,t[l])) l++;
q[++r] = s[i];
if(l < r) t[r-1] = intersection(q[r].a,q[r].a - q[r].b,q[r-1].a,q[r-1].a - q[r-1].b);
}
while(l < r && onright(q[l].a,q[l].b,t[r-1])) r--;
if(r - l <= 1) return false;
return true;
}
double solve(){
double l = 0,r = 10000 + 10, ans = 0;
while(dcmp(r - l)){
double mid = (l + r) / 2;
for(int i=0;i<n;i++) s[i] = (Line){poly[i].a + to[i] * mid,poly[i].b + to[i] * mid};
if(halfplaneintersection()){
ans = mid;
l = mid;
}else r = mid;
}
return ans;
}double Length(Vector A){ //计算向量的长度
return sqrt(Dot(A,A));
}
Vector Normal(Vector A){ //计算单位法向量
double len = Length(A);
return Vector(-A.y / len,A.x / len); //左转90度。
}
int main(){
while(~scanf("%d",&n) && n){
for(int i=0;i<n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y);
for(int i=0;i<n;i++){
poly[i] = (Line){a[i],a[(i+1)%n]};
to[i] = Normal(poly[i].b - poly[i].a);
}
printf("%.6lf\n",solve());
}
return 0;
}