题目大意:给你一个凸包,里面放两个半径相同的圆,问你如果让这两个圆覆盖凸包的面积最大。
两个圆可以覆盖重合,但不是不会跑到墙角折起来。输出放置圆的两个圆的圆心坐标。如果有多种可能,输出任意一种。
思路:
半平面交内推R,求目前这个核最远的两点,因为半径固定,两个圆的圆心离的越开,你们覆盖的凸包的面积也就越大。
1.半平面交内推R
2.暴力扫描一边核(就是一个新的凸包)的点,算出距离最远的两个点,就输出。
代码:78ms c++
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
struct pnode{
double x,y;
pnode(double xx=0.0,double yy=0.0):x(xx),y(yy){}
//绕原点旋转角度a(弧度)
void tansxy(double a){
double tx = x,ty= y;
x = tx*cos(a) - ty*sin(a);
y = tx*sin(a) + ty*cos(a);
}
}p[105],tp[105],q[105];
double dist(pnode p1,pnode p2){
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
//通过两点,确定直线方程
void get_line( pnode p1,pnode p2,double &a,double &b,double &c){
a = p2.y - p1.y;
b = p1.x - p2.x;
c = p2.x*p1.y - p1.x*p2.y;
}
//求交点
pnode line_inter_point(pnode p1,pnode p2,double a,double b,double c){
double u = fabs(a*p1.x+b*p1.y+c);
double v = fabs(a*p2.x+b*p2.y+c);
pnode t;
t.x = ( p1.x*v + p2.x*u )/(u+v);
t.y = ( p1.y*v + p2.y*u )/(u+v);
return t;
}
//顺时针,加入一条边,切割
void cut( pnode p[],int &cnt,double a,double b,double c){
int tmp = 0;
for( int i = 1;i<= cnt;++i){
//当前点在右侧 逆时针为在左侧 改为 if( <eps )
if( a*p[i].x + b*p[i].y + c > -eps)
tp[++tmp] = p[i];
else{
if( a*p[i-1].x + b*p[i-1].y +c > eps )
tp[++tmp] = line_inter_point(p[i-1],p[i],a,b,c);
if( a*p[i+1].x + b*p[i+1].y +c > eps )
tp[++tmp] = line_inter_point(p[i],p[i+1],a,b,c);
}
}
for( int i = 1; i <= tmp ;++i)
p[i] = tp[i];
p[0] = p[tmp];
p[tmp+1] = p[1];
cnt = tmp;
}
void solve(pnode q[],int n,double r){
q[0]=q[n];
q[n+1]=q[1];
for(int i=0;i<=n+1;i++) p[i]=q[i];
int cnt=n;
for(int i=1;i<=n;i++){
double a,b,c;
pnode p1( q[i+1].y-q[i].y ,q[i].x-q[i+1].x);
double k=r/sqrt(p1.x*p1.x+p1.y*p1.y);
p1.x=k*p1.x;p1.y=p1.y*k;
pnode p2 (p1.x+q[i].x,p1.y+q[i].y );
pnode p3 (p1.x+q[i+1].x,p1.y+q[i+1].y );
get_line(p2,p3,a,b,c);
cut(p,cnt,a,b,c);
}
double maxdist=0,d;
pnode p1,p2;
for(int i=1;i<=cnt;i++)
for(int j=1;j<=cnt;j++){
d=dist(p[i],p[j]);
if(d+eps>maxdist){
maxdist=d;
p1=p[i];
p2=p[j];
}
}
printf("%.4lf %.4lf %.4lf %.4lf\n",p1.x,p1.y,p2.x,p2.y);
}
int main()
{
int n,r;
while( ~scanf("%d %d",&n,&r)){
for( int i = 1;i <= n;++i)
scanf("%lf %lf",&q[i].x,&q[i].y);
solve(q,n,r);
}
return 0;
}