您的位置:首页 > 其它

bzoj2823

2015-06-04 20:58 141 查看
最小圆覆盖

有个东西叫作随机增量法,具体可以baidu

这里来说说怎么求三点共圆

这其实就是求两条线段的交点

在编程中,我们解方程是比较麻烦的一个比较好的方法是利用相似三角形

设线段AB,CD交P,则PC:PD=Sabc:Sabd

然后用定比分点就可以求的交点坐标了

const eps=1e-6;

type point=record
x,y:double;
end;

var p:array[0..500010] of point;
i,n,j,k:longint;
r:double;

procedure swap(var a,b:point);
var c:point;
begin
c:=a;
a:=b;
b:=c;
end;

function dis(i,j:longint):double;
begin
exit(sqrt(sqr(p[i].x-p[j].x)+sqr(p[i].y-p[j].y)));
end;

function cov(i:longint):boolean;
begin
if dis(i,0)-r>eps then exit(false)
else exit(true);
end;

procedure little(i,j:longint);
begin
p[0].x:=(p[i].x+p[j].x)/2;
p[0].y:=(p[i].y+p[j].y)/2;
r:=dis(i,j)/2;
end;

function cross(x1,y1,x2,y2:double):double;
begin
exit(x1*y2-x2*y1);
end;

procedure circle(i,j,k:longint);
var ret,xa,ya,xb,yb,xc,yc,xd,yd,t1,t2:double;
begin
ret:=100/dis(i,j);
xa:=(p[i].x+p[j].x)/2; ya:=(p[i].y+p[j].y)/2;
xb:=xa-ret*(p[i].y-p[j].y); yb:=ya+ret*(p[i].x-p[j].x);
ret:=100/dis(j,k);
xc:=(p[j].x+p[k].x)/2; yc:=(p[j].y+p[k].y)/2;
xd:=xc-ret*(p[j].y-p[k].y); yd:=yc+ret*(p[j].x-p[k].x);
t1:=cross(xc-xa,yc-ya,xb-xa,yb-ya);
t2:=cross(xb-xa,yb-ya,xd-xa,yd-ya);
p[0].x:=(t1*xd+t2*xc)/(t1+t2);
p[0].y:=(t1*yd+t2*yc)/(t1+t2);
r:=dis(0,i);
end;

begin
readln(n);
for i:=1 to n do
begin
readln(p[i].x,p[i].y);
swap(p[i],p[trunc(random*i)+1]);
end;
little(1,2);
for i:=3 to n do
if not cov(i) then
begin
little(1,i);
for j:=2 to i-1 do
if not cov(j) then
begin
little(i,j);
for k:=1 to j-1 do
if not cov(k) then circle(i,j,k);
end;
end;
writeln(p[0].x:0:2,' ',p[0].y:0:2,' ',r:0:2);
end.


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: