//大白p263
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <functional>
#include <set>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const double eps=1e-;//精度
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
inline int dcmp(const double& x){//判断double等于0或。。。
if(fabs(x)<eps)return ;else return x<?-:;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
};
typedef Point Vector;
typedef vector<Point> Polygon;
inline Vector operator+(const Vector& a,const Vector& b){return Vector(a.x+b.x,a.y+b.y);}//向量+向量=向量
inline Vector operator-(const Point& a,const Point& b){return Vector(a.x-b.x,a.y-b.y);}//点-点=向量
inline Vector operator*(const Vector& a,const double& p){return Vector(a.x*p,a.y*p);}//向量*实数=向量
inline Vector operator/(const Vector& a,const double& p){return Vector(a.x/p,a.y/p);}//向量/实数=向量
inline bool operator<( const Point& A,const Point& B ){return dcmp(A.x-B.x)<||(dcmp(A.x-B.x)==&&dcmp(A.y-B.y)<);}
inline bool operator==(const Point&a,const Point&b){return dcmp(a.x-b.x)==&&dcmp(a.y-b.y)==;}
inline bool operator!=(const Point&a,const Point&b){return a==b?false:true;}
struct Segment{
Point a,b;
Segment(){}
Segment(Point _a,Point _b){a=_a,b=_b;}
inline bool friend operator<(const Segment& p,const Segment& q){return p.a<q.a||(p.a==q.a&&p.b<q.b);}
inline bool friend operator==(const Segment& p,const Segment& q){return (p.a==q.a&&p.b==q.b)||(p.a==q.b&&p.b==q.a);}
};
struct Circle{
Point c;
double r;
Circle(){}
Circle(Point _c, double _r):c(_c),r(_r) {}
Point point(double a)const{return Point(c.x+cos(a)*r,c.y+sin(a)*r);}
bool friend operator<(const Circle& a,const Circle& b){return a.r<b.r;}
};
struct Line{
Point p;
Vector v;
double ang;
Line() {}
Line(const Point &_p, const Vector &_v):p(_p),v(_v){ang = atan2(v.y, v.x);}
inline bool operator<(const Line &L)const{return ang < L.ang;}
};
inline double Dot(const Vector& a,const Vector& b){return a.x*b.x+a.y*b.y;}//|a|*|b|*cosθ 点积
inline double Length(const Vector& a){return sqrt(Dot(a,a));}//|a| 向量长度
inline double Angle(const Vector& a,const Vector& b){return acos(Dot(a,b)/Length(a)/Length(b));}//向量夹角θ
inline double Cross(const Vector& a,const Vector& b){return a.x*b.y-a.y*b.x;}//叉积 向量围成的平行四边形的面积
inline double Area2(const Point& a,const Point& b,Point c){return Cross(b-a,c-a);}//同上 参数为三个点
inline double DegreeToRadius(const double& deg){return deg/*PI;}
inline double GetRerotateAngle(const Vector& a,const Vector& b){//向量a顺时针旋转theta度得到向量b的方向
double tempa=Angle(a,Vector(,));
if(a.y<) tempa=*PI-tempa;
double tempb=Angle(b,Vector(,));
if(b.y<) tempb=*PI-tempb;
if((tempa-tempb)>) return tempa-tempb;
else return tempa-tempb+*PI;
}
inline double torad(const double& deg){return deg/*PI;}//角度化为弧度
inline Vector Rotate(const Vector& a,const double& rad){//向量逆时针旋转rad弧度
return Vector(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
inline Vector Normal(const Vector& a){//计算单位法线
double L=Length(a);
return Vector(-a.y/L,a.x/L);
}
inline Point GetLineProjection(const Point& p,const Point& a,const Point& b){//点在直线上的投影
Vector v=b-a;
return a+v*(Dot(v,p-a)/Dot(v,v));
}
inline Point GetLineIntersection(Point p,Vector v,Point q,Vector w){//求直线交点 有唯一交点时可用
Vector u=p-q;
double t=Cross(w,u)/Cross(v,w);
return p+v*t;
}
int ConvexHull(Point* p,int n,Point* sol){//计算凸包
sort(p,p+n);
int m=;
for(int i=;i<n;i++){
while(m>&&dcmp(Cross(sol[m-]-sol[m-],p[i]-sol[m-]))<=) m--;
sol[m++]=p[i];
}
int k=m;
for(int i=n-;i>=;i--){
while(m>k&&dcmp(Cross(sol[m-]-sol[m-],p[i]-sol[m-]))<=) m--;
sol[m++]=p[i];
}
if(n>) m--;
return m;
}
double Heron(double a,double b,double c){//海伦公式
double p=(a+b+c)/;
return sqrt(p*(p-a)*(p-b)*(p-c));
}
bool SegmentProperIntersection(const Point& a1,const Point& a2,const Point& b1,const Point& b2){//线段规范相交判定
double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1);
double c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
return dcmp(c1)*dcmp(c2)<&&dcmp(c3)*dcmp(c4)<;
}
double CutConvex(const int& n,Point* poly,const Point& a,const Point& b, vector<Point> result[]){//有向直线a b 切割凸多边形
vector<Point> points;
Point p;
Point p1=a,p2=b;
int cur,pre;
result[].clear();
result[].clear();
result[].clear();
if(n==) return ;
double tempcross;
tempcross=Cross(p2-p1,poly[]-p1);
if(dcmp(tempcross)==) pre=cur=;
else if(tempcross>) pre=cur=;
else pre=cur=;
for(int i=;i<n;i++){
tempcross=Cross(p2-p1,poly[(i+)%n]-p1);
if(dcmp(tempcross)==) cur=;
else if(tempcross>) cur=;
else cur=;
if(cur==pre){
result[cur].push_back(poly[(i+)%n]);
}
else{
p1=poly[i];
p2=poly[(i+)%n];
p=GetLineIntersection(p1,p2-p1,a,b-a);
points.push_back(p);
result[pre].push_back(p);
result[cur].push_back(p);
result[cur].push_back(poly[(i+)%n]);
pre=cur;
}
}
sort(points.begin(),points.end());
if(points.size()<){
return ;
}
else{
return Length(points.front()-points.back());
}
}
double DistanceToSegment(Point p,Segment s){//点到线段的距离
if(s.a==s.b) return Length(p-s.a);
Vector v1=s.b-s.a,v2=p-s.a,v3=p-s.b;
if(dcmp(Dot(v1,v2))<) return Length(v2);
else if(dcmp(Dot(v1,v3))>) return Length(v3);
else return fabs(Cross(v1,v2))/Length(v1);
}
inline bool isPointOnSegment(const Point& p,const Segment& s){
return dcmp(Cross(s.a-p,s.b-p))==&&dcmp(Dot(s.a-p,s.b-p))<;
}
int isPointInPolygon(Point p, Point* poly,int n){//点与多边形的位置关系
int wn=;
for(int i=;i<n;i++){
Point& p2=poly[(i+)%n];
if(isPointOnSegment(p,Segment(poly[i],p2))) return -;//点在边界上
int k=dcmp(Cross(p2-poly[i],p-poly[i]));
int d1=dcmp(poly[i].y-p.y);
int d2=dcmp(p2.y-p.y);
if(k>&&d1<=&&d2>)wn++;
if(k<&&d2<=&&d1>)wn--;
}
if(wn) return ;//点在内部
else return ;//点在外部
}
double PolygonArea(Point* p,int n){//多边形有向面积
double area=;
for(int i=;i<n-;i++)
area+=Cross(p[i]-p[],p[i+]-p[]);
return area/;
}
int GetLineCircleIntersection(Line L,Circle C,Point& p1,Point& p2){//圆与直线交点 返回交点个数
double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y-C.c.y;
double e = a*a + c*c, f = *(a*b+c*d), g = b*b + d*d -C.r*C.r;
double delta = f*f - *e*g;
if(dcmp(delta) < ) return ;//相离
if(dcmp(delta) == ) {//相切
p1=p1=L.p+L.v*(-f/(*e));
return ;
}//相交
p1=(L.p+L.v*(-f-sqrt(delta))/(*e));
p2=(L.p+L.v*(-f+sqrt(delta))/(*e));
return ;
}
double rotating_calipers(Point *ch,int n)//旋转卡壳
{
int q=;
double ans=;
ch[n]=ch[];
for(int p=;p<n;p++)
{
while(Cross(ch[q+]-ch[p+],ch[p]-ch[p+])>Cross(ch[q]-ch[p+],ch[p]-ch[p+]))
q=(q+)%n;
ans=max(ans,max(Length(ch[p]-ch[q]),Length(ch[p+]-ch[q+])));
}
return ans;
}
Polygon CutPolygon(Polygon poly,const Point& a,const Point& b){//用a->b切割多边形 返回左侧
Polygon newpoly;
int n=poly.size();
for(int i=;i<n;i++){
Point c=poly[i];
Point d=poly[(i+)%n];
if(dcmp(Cross(b-a,c-a))>=) newpoly.push_back(c);
if(dcmp(Cross(b-a,c-d))!=){
Point ip=GetLineIntersection(a,b-a,c,d-c);
if(isPointOnSegment(ip,Segment(c,d))) newpoly.push_back(ip);
}
}
return newpoly;
}
int GetCircleCircleIntersection(Circle c1,Circle c2,Point& p1,Point& p2){//求两圆相交
double d=Length(c1.c-c2.c);
if(dcmp(d)==){
if(dcmp(c1.r-c2.r)==) return -;//两圆重合
return ;
}
if(dcmp(c1.r+c2.r-d)<) return ;
if(dcmp(fabs(c1.r-c2.r)-d)>) return ;
double a=Angle(c2.c-c1.c,Vector(,));
double da=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(*c1.r*d));
p1=c1.point(a-da);p2=c1.point(a+da);
if(p1==p2) return ;
return ;
}
inline bool isPointOnleft(Point p,Line L){return dcmp(Cross(L.v,p-L.p))>;}//点在直线左边 线上不算
int HalfplaneIntersection(Line *L,int n,Point* poly){//半平面交
sort(L,L+n);
int first,last;
Point* p=new Point[n];
Line* q=new Line[n];
q[first=last=]=L[];
for(int i=;i<n;i++){
while(first<last&&!isPointOnleft(p[last-],L[i])) last--;
while(first<last&&!isPointOnleft(p[first],L[i])) first++;
q[++last]=L[i];
if(dcmp(Cross(q[last].v,q[last-].v))==){
last--;
if(isPointOnleft(L[i].p,q[last])) q[last]=L[i];
}
if(first<last) p[last-]=GetLineIntersection(q[last-].p,q[last-].v,q[last].p,q[last].v);
}
while(first<last&&!isPointOnleft(p[last-],q[first])) last--;
if(last-first<=) return ;
p[last]=GetLineIntersection(q[last].p,q[last].v,q[first].p,q[first].v);
int m=;
for(int i=first;i<=last;i++) poly[m++]=p[i];
return m;
}
//两点式化为一般式A = b.y-a.y, B = a.x-b.x, C = -a.y*(B)-a.x*(A);
//--------------------------------------
//--------------------------------------
//--------------------------------------
//--------------------------------------
//--------------------------------------
Point point[],ppoint[];
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
int tot = ;
double x,y,r;
for(int i = ;i<n;i++)
{
scanf("%lf%lf%lf",&x,&y,&r);
for(double j = ;j<*PI;j += 0.0032)
{
point[tot++] = Point(x+r*cos(j),y+r*sin(j));
}
}
for(int i = ;i<m;i++)
for(int j = ;j<;j++)
{
scanf("%lf%lf",&x,&y);
point[tot++] = Point(x,y);
}
tot=ConvexHull(point,tot,ppoint);
double ans = ;
Point pre = ppoint[];
for(int i = ;i<tot;i++)
{
ans += Length(ppoint[i]-pre);
pre = ppoint[i];
}
ans += Length(ppoint[]-pre);
printf("%.5f\n",ans);
}
return ;
}

hdu 4667 Building Fence < 计算几何模板>的更多相关文章

  1. HDU 4667 Building Fence 计算几何 凸包+圆

    1.三角形的所有端点 2.过所有三角形的端点对所有圆做切线,得到所有切点. 3.做任意两圆的外公切线,得到所有切点. 对上述所有点求凸包,标记每个点是三角形上的点还是某个圆上的点. 求完凸包后,因为所 ...

  2. HDU 4667 Building Fence(2013多校7 1002题 计算几何,凸包,圆和三角形)

    Building Fence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)To ...

  3. HDU 4667 Building Fence(求凸包的周长)

    A - Building Fence Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u ...

  4. HDU 4667 Building Fence

    题意: 给n个圆和m个三角形,且保证互不相交,用一个篱笆把他们围起来,求最短的周长是多少. 做法:--水过... 把一个圆均匀的切割成500个点,然后求凸包. 注意:求完凸包,在求周长的时候记得要把圆 ...

  5. HDU 5130 Signal Interference(计算几何 + 模板)

    HDU 5130 Signal Interference(计算几何 + 模板) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5130 Descripti ...

  6. 4667 Building Fence 解题报告

    题意:给n个圆和m个三角形,且保证互不相交,用一个篱笆把他们围起来,求最短的周长是多少. 解法1:在每个圆上均匀的取2000个点,求凸包周长就可以水过. 解法2:求出所有圆之间的外公切线的切点,以及过 ...

  7. [hdu4667]Building Fence 计算几何 瞎瘠薄搞

    大致题意: 给出n个圆和m个三角形,求最小的的,能将所有图形覆盖的图形的周长. 正解为求所有三角形顶点与圆的切点以及圆和圆的切点构造凸包,再求路径. 因为要求结果误差<=1e-3 所以 我们可以 ...

  8. lrj计算几何模板

    整理了一下大白书上的计算几何模板. #include <cstdio> #include <algorithm> #include <cmath> #include ...

  9. HDU 5033 Building(单调栈)

    HDU 5033 Building(单调栈) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5033 Description Once upon a ti ...

随机推荐

  1. Centos python 2.6 升级到 2.7

    前几天做了下阿里云的RDS日志相关功能,其工具大都是Python语言编写,但服务器初始化时的Python版本又不满足需求,本身也没有学过Python,因此在问题定位上费了一番周折,最后找朋友帮忙看了下 ...

  2. Educational Codeforces Round 34 A. Hungry Student Problem【枚举】

    A. Hungry Student Problem time limit per test 1 second memory limit per test 256 megabytes input sta ...

  3. Topcoder SRM 145 DIV 1

    Bonuses 模拟 题意:给你一个序列,按照百分比排序,再将百分比取整,再把剩余百分比加到最大的那几个. 题解:按照题意模拟就好.

  4. vim display line number

    cd /etc/vim sudo chmod 777 vimrc add :ser number to vimrc, then save and quit

  5. redis 事件

    事件是 Redis 服务器的核心,它处理两项重要的任务: 文件事件 在多个客户端中实现多路复用,接受它们发来的命令请求,并将命令的执行结果返回给客户端. 时间事件 实现服务器常规操作(server c ...

  6. Jsp2.0自定义标签(第三天)——EL表达式的使用

    1.提出问题: 我们经常会看到这样的jsp页面代码: 浏览器显示: 为什么会在页面输出:Hello World  ,${per}究竟是如何找到“Hello World”的呢? 2.分析问题: 要想解决 ...

  7. OpenCV头文件包含问题

    opencv从2.2版本以后<opencv root>include下有两个文件夹 opencv 和opencv2.从官方的意思来看,它逐渐喜欢用opencv2里面的那种包含头文件的方式. ...

  8. 2017.2.28 activiti实战--第六章--任务表单(二)外置表单

    学习资料:<Activiti实战> 第六章 任务表单(二)外置表单 6.3 外置表单 考虑到动态表单的缺点(见上节),外置表单使用的更多. 外置表单的特点: 页面的原样显示 字段值的自动填 ...

  9. 2016.7.12 Table configuration with catalog null, schema public, and table globalpage did not resolve to any tables(疑)

    在eclipse中运行mybatis的generator插件时,出现如下错误提示: Generation Warnings Occured:Table configuration with catal ...

  10. An internal error occurred Exception caught during execution of commit command

    在工程目录下找到 .git 文件夹 ,找到里面的 index.lock 文件,删掉再commit