如果你理解上一题的把多边形各边向内推进R的含义,那么,这题就是水题了^-^
当各边都向内推进R时,所得交点即可作为半径为R的圆的圆心了,那么,枚举推进后多边形各点的距离,取最远两点,即为答案了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAXN=150;
const double eps=1e-8;
struct point {
double x,y;
};
point pts[MAXN],p[MAXN],q[MAXN];
int n,ansCnt,curCnt; double r;
int DB(double d){
if(d>eps) return 1;
if(d<-eps) return -1;
return 0;
}
void initial(){
for(int i=1;i<=n;i++){
p[i]=pts[i];
}
p[n+1]=p[1];
p[0]=p[n];
ansCnt=n;
}
double dist(point a,point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void getline(point x,point y,double &a,double &b,double &c){
a = y.y - x.y;
b = x.x - y.x;
c = y.x * x.y - x.x * y.y;
}
point intersect(point x,point y,double a,double b,double c){
double u = fabs(a * x.x + b * x.y + c);
double v = fabs(a * y.x + b * y.y + c);
point pt;
pt.x=(x.x * v + y.x * u) / (u + v);
pt.y=(x.y * v + y.y * u) / (u + v);
return pt;
}
void cut(double a,double b,double c){
curCnt=0;
for(int i=1;i<=ansCnt;i++){
if(DB(a*p[i].x+b*p[i].y+c)>=0) q[++curCnt]=p[i];
else{
if(DB(a*p[i-1].x+b*p[i-1].y+c)>0) q[++curCnt]=intersect(p[i],p[i-1],a,b,c);
if(DB(a*p[i+1].x+b*p[i+1].y+c)>0) q[++curCnt]=intersect(p[i],p[i+1],a,b,c);
}
}
for(int i=1;i<=curCnt;i++)
p[i]=q[i];
p[curCnt+1]=p[1];
p[0]=p[curCnt];
ansCnt=curCnt;
}
void slove(double r){
initial();
for(int i=1;i<=n;i++){
point tt,ta,tb;
tt.x=pts[i+1].y-pts[i].y;
tt.y=pts[i].x-pts[i+1].x;
double k=r/sqrt(tt.x*tt.x+tt.y*tt.y);
ta.x=pts[i].x+k*tt.x;
ta.y=pts[i].y+k*tt.y;
tb.x=pts[i+1].x+k*tt.x;
tb.y=pts[i+1].y+k*tt.y;
double a,b,c;
getline(ta,tb,a,b,c);
cut(a,b,c);
}
}
int main(){
while(scanf("%d%lf",&n,&r)!=EOF){
for(int i=1;i<=n;i++)
scanf("%lf%lf",&pts[i].x,&pts[i].y);
pts[n+1]=pts[1];
slove(r);
point ans1,ans2; double dis=0;
ans1=ans2=p[1];
for(int i=1;i<=ansCnt;i++){
for(int j=i+1;j<=ansCnt;j++){
double tmp=dist(p[i],p[j]);
if(tmp>dis){
dis=tmp;
ans1=p[i];
ans2=p[j];
}
}
}
printf("%.4lf %.4lf %.4lf %.4lf
",ans1.x,ans1.y,ans2.x,ans2.y);
}
return 0;
}