【BZOJ2823】【AHOI2012】信号塔 最小圆覆盖 计算几何
2015-06-23 14:04
465 查看
链接:
#include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/46605193"); }
题解之前:
首先最小圆覆盖虽然有三层 forfor 循环,但是它是期望 O(n)O(n) 的。什么?你问我为啥?那我只能呵呵了,50W的 O(n3)O(n^3) 高速跑过。后交的是不求凸包直接跑的,先交的是求了凸包再跑的。。并没有什么差距。
题解:
这道题我们可以先写一份求凸包来缩减点的规模,如果点是随机生成的,那么期望有不到100个点在凸包上,然后就可以乱搞了(其实毛用没有2333)然后这道题需要用到 [最小圆覆盖] (呃其实这道题就是裸的最小圆覆盖……)
最小圆覆盖:
初始圆为 点 11 这个半径为 00 的圆。。for1ni=2for1_{i=2}^n 若 ii 不在已有圆中,则求一个圆周包含 ii 的最小圆。
{
~~~~~~ 圆改为点 ii 这个半径为 00 的圆
~~~~~~for2i−1j=1for2_{j=1}^{i-1} 若 jj 不在已有圆中,则求一个圆周包含 i、ji、j 的最小圆。
~~~~~~{
~~~~~~~~~~~~ 圆改为以线段 (i,j)(i,j) 为直径的圆
~~~~~~~~~~~~for2j−1k=1for2_{k=1}^{j-1} 若 kk 不在已有圆中,则求一个圆周包含 i、j、ki、j、k 的最小圆。
~~~~~~~~~~~~{
~~~~~~~~~~~~~~~~~~ 圆改为三角形 (i,j,k)(i,j,k) 的外接圆
~~~~~~~~~~~~}
~~~~~~}
}
返回圆
真是奇葩。QwQ
代码:
那个求三角形外心不妨自己乱搞,这里的那个是懒得推直接扒的,然后没看懂QwQ#include <cmath> #include <cstdio> #include <iostream> #include <algorithm> #define N 501000 #define eps 1e-7 using namespace std; struct Point { double x,y; Point(double _x=0,double _y=0):x(_x),y(_y){} void read(){scanf("%lf%lf",&x,&y);} bool operator < (const Point &A)const {return fabs(x-A.x)<eps?y<A.y:x<A.x;} double operator - (const Point &A)const {return sqrt((x-A.x)*(x-A.x)+(y-A.y)*(y-A.y));} void print(){printf("%.2lf %.2lf ",x,y);} }p ; struct Circle { Point c; // center double r; Circle(Point _c=Point(0,0),double _r=0):c(_c),r(_r){} bool operator ^ (const Point &A)const{return A-c>r+eps;} // 包含 void print() { c.print(); printf("%.2lf\n",r); } }; inline double xmul(const Point &A,const Point &B,const Point &C) {return (C.y-A.y)*(B.x-A.x)-(B.y-A.y)*(C.x-A.x);} struct Get_Convex_Hull {//求凸包 int stk1 ,top1,stk2 ,top2; Point tp ; void work(Point *p,int &n) { int i; sort(p+1,p+n+1); stk1[top1=1]=1; for(i=2;i<=n;i++) { while(top1>1&&xmul(p[stk1[top1-1]],p[stk1[top1]],p[i])>-eps)top1--; stk1[++top1]=i; } stk2[top2=1]=n; for(i=n-1;i;i--) { while(top2>1&&xmul(p[stk2[top2-1]],p[stk2[top2]],p[i])>-eps)top2--; stk2[++top2]=i; } n=0; for(i=1;i<top1;i++)tp[++n]=p[stk1[i]]; for(i=1;i<top2;i++)tp[++n]=p[stk2[i]]; for(i=1;i<=n;i++)p[i]=tp[i]; } }gch; struct Get_Min_Circle_Cover { Point circumcenter(const Point &a,const Point &b,const Point &c) {//返回三角形的外心 我并不知道这是什么鬼。。好强的样子。 Point ret; double a1=b.x-a.x,b1=b.y-a.y,c1=(a1*a1+b1*b1)/2; double a2=c.x-a.x,b2=c.y-a.y,c2=(a2*a2+b2*b2)/2; double d=a1*b2-a2*b1; ret.x=a.x+(c1*b2-c2*b1)/d; ret.y=a.y+(a1*c2-a2*c1)/d; return ret; } Circle work(int n) { random_shuffle(p+1,p+n+1); Circle C=Circle(p[1],0); int i,j,k; for(i=2;i<=n;i++)if(C^p[i]) { C=Circle(p[i],0); for(j=1;j<i;j++)if(C^p[j]) { C.c=Point((p[i].x+p[j].x)/2,(p[i].y+p[j].y)/2); C.r=p[j]-C.c; for(k=1;k<j;k++)if(C^p[k])//求外接圆圆心,要求三点不能共线 C.c=circumcenter(p[i],p[j],p[k]),C.r=C.c-p[i]; } } return C; } }gmcc; int main() { // freopen("test.in","r",stdin); int i=0,n; scanf("%d",&n); for(i=1;i<=n;i++)p[i].read(); // gch.work(p,n); Circle ret=gmcc.work(n); ret.print(); return 0; }
相关文章推荐
- ORACLE常用SQL命令
- JS小知识点三(for gis):openAtStart
- JPA常用注解
- Linux ALSA声卡驱动之五:移动设备中的ALSA(ASoC)
- C++函数参数中的省略号用法分析
- 【剑指offer 面试题21】包含min函数的栈
- Android 如何让EditText不自动获取焦点
- 设计模式----状态模式 实例
- VS2008在XP系统托盘气泡提示不成功解决办法
- 【iOS知识学习】_视图控制对象生命周期-init、viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear等的区别及用途
- 如何查看php版本
- 15 3Sum(寻找三个数之和为指定数的集合Medium)
- linux grep命令使用的一些心得
- 64位开源处理器Rocket的源代码简单介绍
- CV各技术论坛及QQ群
- Android中的Interpolator
- QTPtest中Action种类
- Linux ALSA声卡驱动之四:Control设备的创建
- 第三个sprint冲刺第三阶段
- php 登陆后台验证代码