bzoj1337

洛谷P1742

用随机增量法。讲解:https://blog.csdn.net/jokerwyt/article/details/79221345

设点集A的最小覆盖圆为g(A)

可以发现:
1.g(A)是唯一的
2.g(A)可以由<=3个点唯一确定
①由一个点确定(所有点重合时)
②由两个点确定(圆直径必定为两点连线)
③由三个点确定(圆必定是过三点的唯一圆)

把A中在g(A)上的点叫做关键点
可以发现:若点b不在g(A)内(b不属于A),则b是g(A+b)的关键点
证明:如果b不是g(A+b)的关键点,即b在g(A+b)内,那么显然g(A+b)=g(A),b在g(A)内,与题意矛盾

记点l,点l+1,点l+2,..,点r构成的集合为l..r
现在题目就是要求g(1..i)

设g(A,B)表示点集A的最小覆盖圆,并且点集B中所有点都在这个圆上
设Cir(x,y)表示一个圆心在点x,半径为y的圆
设Cir(a,b,c)表示由a,b,c三点确定的圆

g(1..i)
=g(1..i-1)(如果i属于g(1..i-1))
=g(1..i-1,i)(如果i不属于g(1..i-1))

g(空集,i)=Cir(i,0)

g(1..p,i)
=g(1..p-1,i)(如果p属于g(1..p-1,i))
=g(1..p-1,{i,p})(如果p不属于g(1..p-1,i))

g(空集,{i,j})=Cir((i,j中点),dis(i,j)/2)

g(1..q,{i,p})
=g(1..q-1,{i,p})(如果q属于g(1..q,{i,p}))
=g(1..q-1,{i,p,q})(如果q不属于g(1..q,{i,p}))

g(任意集合,{i,j,k})=Cir(i,j,k)

可以把以上过程改写成循环(以上相当于给出了从g(1..i-1)转移到g(1..i)的方法)

(以下代码交洛谷)

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<ctime>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
namespace X
{
const double eps=1e-;
struct Point
{
double x,y;
Point(double x=,double y=):x(x),y(y){}
};
typedef Point Vec;
Vec operator+(const Vec& a,const Vec& b)
{
return Vec(a.x+b.x,a.y+b.y);
}
Vec operator-(const Vec& a,const Vec& b)
{
return Vec(a.x-b.x,a.y-b.y);
}
Vec operator*(double a,const Vec& b)
{
return Vec(a*b.x,a*b.y);
}
Vec operator*(const Vec& a,double b)
{
return Vec(b*a.x,b*a.y);
}
Vec operator/(const Vec& a,double b)
{
return Vec(a.x/b,a.y/b);
}
int dcmp(double x)
//正为1,负为-1,0为0
{
if(fabs(x)<eps) return ;
return x<?-:;
}
bool operator==(const Vec& a,const Vec& b)
//判向量相等
{
return dcmp(a.x-b.x)==&&dcmp(a.y-b.y)==;
}
double dot(const Vec& a,const Vec& b)
//点积
{
return a.x*b.x+a.y*b.y;
}
double cross(const Vec& a,const Vec& b)
//叉积
{
return a.x*b.y-a.y*b.x;
}
double len(const Vec& x)
//向量长度
{
return sqrt(dot(x,x));
}
double angle(const Vec& a,const Vec& b)
//夹角,0~180°
{
return acos(dot(a,b)/len(a)/len(b));
}
double angle1(const Vec& a,const Vec& b)
//夹角,带方向,a到b逆时针为正,顺时针为负,共线为0
{
return acos(dot(a,b)/len(a)/len(b))*(dcmp(cross(a,b)));
}
Vec rotate(const Vec& a,double rad)
//旋转,正为逆时针,负为顺时针
{
return Vec(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
Vec normal(const Vec& x)
//单位法线,左转90°后除以自身长度
{
double l=len(x);
return Vec(-x.y/l,x.x/l);
}
Vec normal1(const Vec& x)
//法线,不归一化
{
return Vec(-x.y,x.x);
}
Point lineline(const Point& p,const Vec& v,const Point& q,const Vec& w)
//直线交点,GetLineIntersection
{
return p+v*cross(w,p-q)/cross(v,w);
}
double ptline(const Point& p,const Point& a,const Point& b)
//point_to_line,点到直线距离,DistanceToLine
{
Vec v1=b-a,v2=p-a;
return fabs(cross(v1,v2)/len(v1));
}
double ptseg(const Point& p,const Point& a,const Point& b)
//point_to_segment,点到线段距离,DistanceToSegment
{
if(a==b) return len(p-a);
//Vec v1=b-a,v2=a-p,v3=p-b;
Vec v1=b-a,v2=p-a,v3=p-b;
if(dcmp(dot(v1,v2))<) return len(v2);
else if(dcmp(dot(v1,v3))>) return len(v3);
else return fabs(cross(v1,v2)/len(v1));
}
double area2(const Point& a,const Point& b,const Point& c)
//叉积对应平行四边形的面积
{
return cross(b-a,c-a);
}
double thrarea(const Point& a,const Point& b,const Point& c)
//三角形面积,绝对值
{
return fabs(cross(b-a,c-a)/);
}
bool ifpar(const Vec& a,const Vec& b)
//ifParallel
//是否共线/平行
{
return dcmp(cross(a,b))==;
}
Point pointline(const Point& p,const Point& a,const Vec& v)
//点在直线上投影,GetLineProjection
{
return a+v*(dot(p-a,v)/dot(v,v));
}
double sqr(double x){return x*x;}
double dis(const Point &x,const Point &y)
{
return sqrt(sqr(x.x-y.x)+sqr(x.y-y.y));
}
};
using namespace X;
Point p[];
int n;
Point a;
double r;
void make(const Point &x,const Point &y)
{
Vec t=(y-x)/;
a=x+t;
r=len(t);
}
void make(const Point &x,const Point &y,const Point &z)
{
Vec t1=(y-x)/,t2=(z-y)/;
Point x1=x+t1,y1=y+t2;
t1=normal1(t1);t2=normal1(t2);
a=lineline(x1,t1,y1,t2);
r=dis(a,x);
}
bool ok(const Point &x)
{
return dis(x,a)<=r;
}
int main()
{
int i,j,k;
srand(time());
scanf("%d",&n);
for(i=;i<=n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
random_shuffle(p+,p+n+);
a=p[];r=;
for(i=;i<=n;i++)
if(!ok(p[i]))
{
a=p[i];r=;
for(j=;j<i;j++)
if(!ok(p[j]))
{
make(p[i],p[j]);
for(k=;k<j;k++)
if(!ok(p[k]))
{
make(p[i],p[j],p[k]);
}
}
}
printf("%.10f\n",r);
printf("%.10f %.10f\n",a.x,a.y);
return ;
}

bzoj2823

洛谷P2533

此题同上面题,改一下输出格式就一样

bzoj数据稍微有点卡精度,把存储半径改成存储半径的平方就可以A了

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<ctime>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
namespace X
{
const double eps=1e-;
struct Point
{
double x,y;
Point(double x=,double y=):x(x),y(y){}
};
typedef Point Vec;
Vec operator+(const Vec& a,const Vec& b)
{
return Vec(a.x+b.x,a.y+b.y);
}
Vec operator-(const Vec& a,const Vec& b)
{
return Vec(a.x-b.x,a.y-b.y);
}
Vec operator*(double a,const Vec& b)
{
return Vec(a*b.x,a*b.y);
}
Vec operator*(const Vec& a,double b)
{
return Vec(b*a.x,b*a.y);
}
Vec operator/(const Vec& a,double b)
{
return Vec(a.x/b,a.y/b);
}
int dcmp(double x)
//正为1,负为-1,0为0
{
if(fabs(x)<eps) return ;
return x<?-:;
}
bool operator==(const Vec& a,const Vec& b)
//判向量相等
{
return dcmp(a.x-b.x)==&&dcmp(a.y-b.y)==;
}
double dot(const Vec& a,const Vec& b)
//点积
{
return a.x*b.x+a.y*b.y;
}
double cross(const Vec& a,const Vec& b)
//叉积
{
return a.x*b.y-a.y*b.x;
}
double len(const Vec& x)
//向量长度
{
return sqrt(dot(x,x));
}
double angle(const Vec& a,const Vec& b)
//夹角,0~180°
{
return acos(dot(a,b)/len(a)/len(b));
}
double angle1(const Vec& a,const Vec& b)
//夹角,带方向,a到b逆时针为正,顺时针为负,共线为0
{
return acos(dot(a,b)/len(a)/len(b))*(dcmp(cross(a,b)));
}
Vec rotate(const Vec& a,double rad)
//旋转,正为逆时针,负为顺时针
{
return Vec(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
Vec normal(const Vec& x)
//单位法线,左转90°后除以自身长度
{
double l=len(x);
return Vec(-x.y/l,x.x/l);
}
Vec normal1(const Vec& x)
//法线,不归一化
{
return Vec(-x.y,x.x);
}
Point lineline(const Point& p,const Vec& v,const Point& q,const Vec& w)
//直线交点,GetLineIntersection
{
return p+v*cross(w,p-q)/cross(v,w);
}
double ptline(const Point& p,const Point& a,const Point& b)
//point_to_line,点到直线距离,DistanceToLine
{
Vec v1=b-a,v2=p-a;
return fabs(cross(v1,v2)/len(v1));
}
double ptseg(const Point& p,const Point& a,const Point& b)
//point_to_segment,点到线段距离,DistanceToSegment
{
if(a==b) return len(p-a);
//Vec v1=b-a,v2=a-p,v3=p-b;
Vec v1=b-a,v2=p-a,v3=p-b;
if(dcmp(dot(v1,v2))<) return len(v2);
else if(dcmp(dot(v1,v3))>) return len(v3);
else return fabs(cross(v1,v2)/len(v1));
}
double area2(const Point& a,const Point& b,const Point& c)
//叉积对应平行四边形的面积
{
return cross(b-a,c-a);
}
double thrarea(const Point& a,const Point& b,const Point& c)
//三角形面积,绝对值
{
return fabs(cross(b-a,c-a)/);
}
bool ifpar(const Vec& a,const Vec& b)
//ifParallel
//是否共线/平行
{
return dcmp(cross(a,b))==;
}
Point pointline(const Point& p,const Point& a,const Vec& v)
//点在直线上投影,GetLineProjection
{
return a+v*(dot(p-a,v)/dot(v,v));
}
double sqr(double x){return x*x;}
double dis2(const Point &x,const Point &y)
{
return sqr(x.x-y.x)+sqr(x.y-y.y);
}
double len2(const Vec &x){return dot(x,x);}
};
using namespace X;
Point p[];
int n;
Point a;
double r2;
void make(const Point &x,const Point &y)
{
Vec t=(y-x)/;
a=x+t;
r2=len2(t);
}
void make(const Point &x,const Point &y,const Point &z)
{
Vec t1=(y-x)/,t2=(z-y)/;
Point x1=x+t1,y1=y+t2;
t1=normal1(t1);t2=normal1(t2);
a=lineline(x1,t1,y1,t2);
r2=dis2(a,x);
}
bool ok(const Point &x)
{
return dcmp(dis2(x,a)-r2)<=;
}
int main()
{
int i,j,k;
srand(time());
scanf("%d",&n);
for(i=;i<=n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
random_shuffle(p+,p+n+);
a=p[];r2=;
for(i=;i<=n;i++)
if(!ok(p[i]))
{
a=p[i];r2=;
for(j=;j<i;j++)
if(!ok(p[j]))
{
make(p[i],p[j]);
for(k=;k<j;k++)
if(!ok(p[k]))
{
make(p[i],p[j],p[k]);
}
}
}
printf("%.2f %.2f ",a.x,a.y);
printf("%.2f\n",sqrt(r2));
return ;
}

(bzoj1337 || 洛谷P1742 最小圆覆盖 )|| (bzoj2823 || 洛谷P2533 [AHOI2012]信号塔)的更多相关文章

  1. 洛谷 P1742 最小圆覆盖 (随机增量)

    题目链接:P1742 最小圆覆盖 题意 给出 N 个点,求最小的包含所有点的圆. 思路 随机增量 最小圆覆盖一般有两种做法:随机增量和模拟退火.随机增量的精确度更高,这里介绍随机增量的做法. 先将所有 ...

  2. 洛谷P1742 最小圆覆盖(计算几何)

    题面 传送门 题解 之前只是在抄题解--这篇才算是真正自己想的吧-- 首先我们把输入序列给\(random\)一下防止出题人好心送你一个毒瘤序列 我们设\(r\)为当前最大半径,\(o\)为此时对应圆 ...

  3. 洛谷P1742 最小圆覆盖(计算几何)

    题意 题目链接 Sol 暴力做法是\(O(n^3)\)枚举三个点然后check一下是否能包含所有点 考虑一种随机算法,首先把序列random_shuffle一下. 然后我们枚举一个点\(i\),并维护 ...

  4. 【BZOJ2823】[AHOI2012]信号塔(最小圆覆盖)

    [BZOJ2823][AHOI2012]信号塔(最小圆覆盖) 题面 BZOJ 洛谷 相同的题: BZOJ1 BZOJ2 洛谷 题解 模板题... #include<iostream> #i ...

  5. 2018.07.04 BZOJ 2823: AHOI2012信号塔(最小圆覆盖)

    2823: [AHOI2012]信号塔 Time Limit: 10 Sec Memory Limit: 128 MB Description 在野外训练中,为了确保每位参加集训的成员安全,实时的掌握 ...

  6. bzoj2823[AHOI2012]信号塔

    2823: [AHOI2012]信号塔 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1190  Solved: 545[Submit][Status ...

  7. 最小圆覆盖(洛谷 P1742 增量法)

    题意:给定N个点,求最小圆覆盖的圆心喝半径.保留10位小数点. N<1e5: 思路:因为精度要求较高,而且N比较大,所以三分套三分的复杂度耶比较高,而且容易出错. 然是写下增量法吧. 伪代码加深 ...

  8. BZOJ2823 [AHOI2012]信号塔 【最小圆覆盖】

    题目链接 BZOJ2823 题解 最小圆覆盖模板 都懒得再写一次 #include<iostream> #include<cstdio> #include<cmath&g ...

  9. bzoj2823: [AHOI2012]信号塔&&1336: [Balkan2002]Alien最小圆覆盖&&1337: 最小圆覆盖

    首先我写了个凸包就溜了 这是最小圆覆盖问题,今晚学了一下 先随机化点,一个个加入 假设当前圆心为o,半径为r,加入的点为i 若i不在圆里面,令圆心为i,半径为0 再重新从1~i-1不停找j不在圆里面, ...

随机推荐

  1. 转载的C#学习笔记

    转载地址:http://www.cnblogs.com/renyanlei/p/4075065.html 最近在一个培训机构里面教授Net知识.每天都会带领学生学习c#知识.我希望把每天学习的笔记记录 ...

  2. java多线程-多线程常识

    线程和进程的区别是什么?进程是一个正在运行的软件程序,打开资源管理器可以看到好多正在运行的进程,而线程则是程序中的顺序控制流,只能使用分配给程序的资源和环境.一个进程至少存在一个线程(主线程). 在j ...

  3. hibernate入门(-)

    1.struts2的支持 在web.xml中配置struts2的支持 <?xml version="1.0" encoding="UTF-8"?> ...

  4. Swing项目编译成exe,并且打包成安装文件(一)

    我们一般用java做Swing项目的时候一般都是只能在Myeclipse里面运行,那么怎么把我们的项目打包成exe可以直接双击运行呢? 初始工作:为了不让用户安装java环境,所以我们先新建一个文件夹 ...

  5. git解决冲突方式

    Git解决冲突 安装beyond compare 4 2.配置git对比工具 #difftool 配置 git config --global diff.tool bc4 git config --g ...

  6. BZOJ_4026_dC Loves Number Theory _主席树+欧拉函数

    BZOJ_4026_dC Loves Number Theory _主席树+欧拉函数 Description  dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯 竭 ...

  7. C++之自己实现的String类全部

    一:回顾 (1)c++中的string类是在面试中和笔试中经常考的题目: 工程代码免费下载 string类的自行实现 (2)c++中的string类和fstream类合起来是处理外部数据的利器: (3 ...

  8. Redis配置主从架构,实现读写分离

    Redis的主从架构,能帮助我们实现读多,写少的情况,下面配置Redis架构,很简单. 准备环境 vmware + rhel-server-7.0(101,102,103)+redis-3.2.0 1 ...

  9. bzoj3680

    $模拟退火$ $这种全局最优的问题用模拟退火$ $模拟退火就是每次向四周随机移动,移动的幅度和温度成正比,如果新的位置更优就接受,否则按一定概率接收,概率和温度成正比$ $最后稳定后再在最优解附近蹦跶 ...

  10. bzoj2806

    广义后缀自动机+二分+单调队列+dp 这道题其实就是一个简单dp,dp[i]表示匹配到i最长匹配多少,设val[i]表示当前位置和原串的最长公共长度,二分的长度是L,那么要求dp[i]=max(dp[ ...