题解
- 多边形向内部推进r个单位,判断是否存在半平面交。然后求新的多边形上距离最远的两点。直接暴力,不用旋转卡壳。
- 注意如果半平面交可能是一个点。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
const double eps = 1e-8;
double const inf = 1e9;
int const N = 100 + 10;
int n;
double r;
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],p[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;
}
int 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--;
t[r] = intersection(q[r].a,q[r].a - q[r].b,q[l].a,q[l].a - q[l].b);
if(r - l <= 1) return 0;
int m = 0;
for(int i=l;i<=r;i++) p[m++] = t[i];
return m;
}
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度。
}
double solve(){
int m = halfplaneintersection();
Point p1 = p[0], p2 = p[0];
double ans = 0;
for(int i=0;i<m-1;i++){
for(int j=i+1;j<m;j++){
double dis = Length(p[i] - p[j]);
if(ans < dis){ //注意取等号,退化成一个点
ans = dis;
p1 = p[i];
p2 = p[j];
}
}
}
printf("%.4f %.4f %.4f %.4f\n",p1.x,p1.y,p2.x,p2.y);
}
int main(){
while(~scanf("%d%lf",&n,&r)){
for(int i=0;i<n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y);
for(int i=0;i<n;i++){
Vector to = Normal(a[i] - a[(i+1)%n]); //法向量
s[i] = (Line){a[(i+1)%n] + to * r,a[i] + to * r};
}
solve();
}
return 0;
}