最小覆盖圆模板+例题两题
🎈最小覆盖圆模板
#include<bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false)
#define mem(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define ll long long
#define mod 1000000007
#define inf 0x7f
#define eps 1e-7
#define LD double
#define ull unsigned long long
#define y1 yy1
#define nxt(i) ((i+1)%s.size())
#define pb push_back
using namespace std;
int sgn(LD x){
return fabs(x)<eps ? 0:(x>0 ? 1:-1);
}
struct P;
struct L;
typedef P V;
struct P{
LD x,y;
explicit P(LD x=0,LD y=0):x(x),y(y){}
explicit P(const L& l);
};
struct L{
P s,t;
L(){}
L(P s,P t):s(s),t(t){}
};
struct C{
P p;LD r;
C(LD x=0,LD y=0,LD r=0):p(x,y),r(r){}
C(P p,LD r):p(p),r(r){}
};
P operator +(const P& a, const P& b) { return P(a.x + b.x, a.y + b.y); }
P operator -(const P& a, const P& b) { return P(a.x - b.x, a.y - b.y); }
P operator *(const P& a, LD k) { return P(a.x * k, a.y * k); }
P operator /(const P& a, LD k) { return P(a.x / k, a.y / k); }
bool operator <(const P& a,const P& b){return sgn(a.x - b.x)<0 || (sgn(a.x - b.x)==0 && sgn(a.y - b.y)<0);}
bool operator ==(const P& a,const P& b){ return !sgn(a.x - b.x) && !sgn(a.y - b.y);}
P::P(const L& l){ *this = l.t - l.s; }
ostream &operator <<(ostream &os,const P &p){return (os << "(" << p.x << "," << p.y << ")");}
istream &operator >>(istream& is, P& p){return (is>>p.x>>p.y);}
LD dist(const P& p) { return sqrt(p.x * p.x + p.y * p.y);}
LD dot(const V& a, const V& b) { return a.x * b.x + a.y * b.y;}
LD det(const V& a, const V& b) { return a.x * b.y - a.y * b.x;}
LD cross(const P& s, const P& t, const P& o = P()) { return det(s - o, t - o);}
P ccc(P a,P b){return (a+b)/2;}
bool pic(const P& p,const C& c){
return sgn(dist(p-c.p)-c.r)<=0;
}
P RotateCW90(const P& p){
return P(p.y,-p.x);
}
struct LV{
P p,v;LD ang;
LV(){}
LV(P s,P t):p(s),v(t-s){ang=atan2(v.y,v.x);}
};
P l_in(const LV &a,const LV& b){
P u=a.p-b.p;LD t=cross(b.v,u)/cross(a.v,b.v);
return a.p+a.v*t;
}
P ccp(P a,P b,P c){
b=(a+b)/2;
c=(a+c)/2;
return l_in({b,b+RotateCW90(a-b)},{c,c+RotateCW90(a-c)});
}
C mincc(const vector<P>& in){
vector<P>a(in.begin(),in.end());
random_shuffle(a.begin(),a.end());
P c=a[0];LD r=0;int n=a.size();
for(int i=1;i<n;i++){
if(!pic(a[i],{c,r})){
c=a[i];r=0;
for(int j=0;j<i;j++){
if(!pic(a[j],{c,r})){
c=ccc(a[i],a[j]);
r=dist(a[j]-c);
for(int k=0;k<j;k++){
if(!pic(a[k],{c,r})){
c=ccp(a[i],a[j],a[k]);
r=dist(a[k]-c);
}
}
}
}
}
}
return {c,r};
}
🎈hdu4720
题意
给定四个点,需判断第四个点是否在前三个点的最小覆盖圆上
AC代码
#include<bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false)
#define mem(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define ll long long
#define mod 1000000007
#define inf 0x7f
#define eps 1e-7
#define LD double
#define ull unsigned long long
#define y1 yy1
#define nxt(i) ((i+1)%s.size())
#define pb push_back
using namespace std;
int sgn(LD x){
return fabs(x)<eps ? 0:(x>0 ? 1:-1);
}
struct P;
struct L;
typedef P V;
struct P{
LD x,y;
explicit P(LD x=0,LD y=0):x(x),y(y){}
explicit P(const L& l);
};
struct L{
P s,t;
L(){}
L(P s,P t):s(s),t(t){}
};
struct C{
P p;LD r;
C(LD x=0,LD y=0,LD r=0):p(x,y),r(r){}
C(P p,LD r):p(p),r(r){}
};
P operator +(const P& a, const P& b) { return P(a.x + b.x, a.y + b.y); }
P operator -(const P& a, const P& b) { return P(a.x - b.x, a.y - b.y); }
P operator *(const P& a, LD k) { return P(a.x * k, a.y * k); }
P operator /(const P& a, LD k) { return P(a.x / k, a.y / k); }
bool operator <(const P& a,const P& b){return sgn(a.x - b.x)<0 || (sgn(a.x - b.x)==0 && sgn(a.y - b.y)<0);}
bool operator ==(const P& a,const P& b){ return !sgn(a.x - b.x) && !sgn(a.y - b.y);}
P::P(const L& l){ *this = l.t - l.s; }
ostream &operator <<(ostream &os,const P &p){return (os << "(" << p.x << "," << p.y << ")");}
istream &operator >>(istream& is, P& p){return (is>>p.x>>p.y);}
LD dist(const P& p) { return sqrt(p.x * p.x + p.y * p.y);}
LD dot(const V& a, const V& b) { return a.x * b.x + a.y * b.y;}
LD det(const V& a, const V& b) { return a.x * b.y - a.y * b.x;}
LD cross(const P& s, const P& t, const P& o = P()) { return det(s - o, t - o);}
P ccc(P a,P b){return (a+b)/2;}
bool pic(const P& p,const C& c){
return sgn(dist(p-c.p)-c.r)<=0;
}
P RotateCW90(const P& p){
return P(p.y,-p.x);
}
struct LV{
P p,v;LD ang;
LV(){}
LV(P s,P t):p(s),v(t-s){ang=atan2(v.y,v.x);}
};
P l_in(const LV &a,const LV& b){
P u=a.p-b.p;LD t=cross(b.v,u)/cross(a.v,b.v);
return a.p+a.v*t;
}
P ccp(P a,P b,P c){
b=(a+b)/2;
c=(a+c)/2;
return l_in({b,b+RotateCW90(a-b)},{c,c+RotateCW90(a-c)});
}
C mincc(const vector<P>& in){
vector<P>a(in.begin(),in.end());
random_shuffle(a.begin(),a.end());
P c=a[0];LD r=0;int n=a.size();
for(int i=1;i<n;i++){
if(!pic(a[i],{c,r})){
c=a[i];r=0;
for(int j=0;j<i;j++){
if(!pic(a[j],{c,r})){
c=ccc(a[i],a[j]);
r=dist(a[j]-c);
for(int k=0;k<j;k++){
if(!pic(a[k],{c,r})){
c=ccp(a[i],a[j],a[k]);
r=dist(a[k]-c);
}
}
}
}
}
}
return {c,r};
}
int main(){
srand(time(0));
int n;scanf("%d",&n);
int cc=0;
while(n--){
vector<P>p1;
for(int i=0;i<3;i++){
double x,y;
scanf("%lf%lf",&x,&y);
p1.pb(P{x,y});
}
LD xx,yy;
scanf("%lf%lf",&xx,&yy);
C ans=mincc(p1);
cc++;
if(pic(P{xx,yy},ans)){
printf("Case #%d: Danger\n",cc);
}
else{
printf("Case #%d: Safe\n",cc);
}
}
return 0;
}
/*
*/
🎈 A——Weird Flecks, But OK
题意
钻头只能垂直于其一个面进入立方体一次。立方体的面平行于坐标轴。
鉴于缺陷的(x,y,z)位置,并且将缺陷的大小忽略不计,一次操作中可用于去除缺陷的最小直径的钻头是多少?
思路
xy,yz,xz三种圆求第四个点的最小距离
AC代码
#include<bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false)
#define mem(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define ll long long
#define mod 1000000007
#define inf 0x7f
#define eps 1e-7
#define LD double
#define ull unsigned long long
#define y1 yy1
#define nxt(i) ((i+1)%s.size())
#define pb push_back
using namespace std;
int sgn(LD x){
return fabs(x)<eps ? 0:(x>0 ? 1:-1);
}
struct P;
struct L;
typedef P V;
struct P{
LD x,y;
explicit P(LD x=0,LD y=0):x(x),y(y){}
explicit P(const L& l);
};
struct L{
P s,t;
L(){}
L(P s,P t):s(s),t(t){}
};
struct C{
P p;LD r;
C(LD x=0,LD y=0,LD r=0):p(x,y),r(r){}
C(P p,LD r):p(p),r(r){}
};
P operator +(const P& a, const P& b) { return P(a.x + b.x, a.y + b.y); }
P operator -(const P& a, const P& b) { return P(a.x - b.x, a.y - b.y); }
P operator *(const P& a, LD k) { return P(a.x * k, a.y * k); }
P operator /(const P& a, LD k) { return P(a.x / k, a.y / k); }
bool operator <(const P& a,const P& b){return sgn(a.x - b.x)<0 || (sgn(a.x - b.x)==0 && sgn(a.y - b.y)<0);}
bool operator ==(const P& a,const P& b){ return !sgn(a.x - b.x) && !sgn(a.y - b.y);}
P::P(const L& l){ *this = l.t - l.s; }
ostream &operator <<(ostream &os,const P &p){return (os << "(" << p.x << "," << p.y << ")");}
istream &operator >>(istream& is, P& p){return (is>>p.x>>p.y);}
LD dist(const P& p) { return sqrt(p.x * p.x + p.y * p.y);}
LD dot(const V& a, const V& b) { return a.x * b.x + a.y * b.y;}
LD det(const V& a, const V& b) { return a.x * b.y - a.y * b.x;}
LD cross(const P& s, const P& t, const P& o = P()) { return det(s - o, t - o);}
P ccc(P a,P b){return (a+b)/2;}
bool pic(const P& p,const C& c){
return sgn(dist(p-c.p)-c.r)<=0;
}
P RotateCW90(const P& p){
return P(p.y,-p.x);
}
struct LV{
P p,v;LD ang;
LV(){}
LV(P s,P t):p(s),v(t-s){ang=atan2(v.y,v.x);}
};
P l_in(const LV &a,const LV& b){
P u=a.p-b.p;LD t=cross(b.v,u)/cross(a.v,b.v);
return a.p+a.v*t;
}
P ccp(P a,P b,P c){
b=(a+b)/2;
c=(a+c)/2;
return l_in({b,b+RotateCW90(a-b)},{c,c+RotateCW90(a-c)});
}
LD mincc(const vector<P>& in){
vector<P>a(in.begin(),in.end());
random_shuffle(a.begin(),a.end());
P c=a[0];LD r=0;int n=a.size();
for(int i=1;i<n;i++){
if(!pic(a[i],{c,r})){
c=a[i];r=0;
for(int j=0;j<i;j++){
if(!pic(a[j],{c,r})){
c=ccc(a[i],a[j]);
r=dist(a[j]-c);
for(int k=0;k<j;k++){
if(!pic(a[k],{c,r})){
c=ccp(a[i],a[j],a[k]);
r=dist(a[k]-c);
}
}
}
}
}
}
return r;
}
vector<P>p1,p2,p3;
int main(){
srand(time(0));
int n;scanf("%d",&n);
for(int i=0;i<n;i++){
double x,y,z;
scanf("%lf%lf%lf",&x,&y,&z);
p1.pb(P{x,y});
p2.pb(P{x,z});
p3.pb(P{z,y});
}
double ans=min(mincc(p1),min(mincc(p2),mincc(p3)));
printf("%f\n",ans*2);
return 0;
}