题意:给n个圆和m个三角形,且保证互不相交,用一个篱笆把他们围起来,求最短的周长是多少。

解法1:在每个圆上均匀的取2000个点,求凸包周长就可以水过。

解法2:求出所有圆之间的外公切线的切点,以及过三角形每个顶点的的直线和圆的切点,和三角形的三个顶点。这些点做凸包确定篱笆边上的图形。凸包的边和圆弧之和即为所求。求圆弧长度的时候要判断是优弧还是劣弧。用叉积判断两个向量的方向关系即可。

//Time:218MS
//Memory:860K
include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
const double EPS = 1e-10;
const double PI = acos(-1.0);
const int MAXN = 55; int dcmp(double x)
{
if(fabs(x)<EPS) return 0;
return x<0? -1:1;
}
double sqr(double x)
{
return x*x;
}
struct Point{
double x,y;
bool tp;
int id;
Point(){}
Point(double a,double b):x(a),y(b){}
Point operator +(const Point &a)const{return Point(x+a.x,y+a.y);}
Point operator -(const Point &a)const{return Point(x-a.x,y-a.y);}
Point operator *(double k) const{return Point(x*k,y*k);}
Point operator /(double k) const{return Point(x/k,y/k);}
bool operator <(const Point &a)const
{
return dcmp(x-a.x)<0||(dcmp(x-a.x)==0&&dcmp(y-a.y)<0);
}
bool operator ==(const Point &a)const
{
return dcmp(x-a.x)==0&&dcmp(y-a.y)==0;
}
Point trunc(double d)
{
double dist(Point ,Point);
double len = dist(*this,Point(0,0));
return Point(x*d/len,y*d/len);
}
Point rotate(double a)
{
return Point(x*cos(a)-y*sin(a),y*cos(a)+x*sin(a));
}
void input(){scanf("%lf%lf",&x,&y);}
};
struct Circle{
Point o;
double r;
Circle(){}
Circle(Point a,double b):o(a),r(b){}
double area(){return sqr(r)*PI;}
double len(double ang){return r*ang;}
};
struct Tri{
Point p[3];
};
typedef Point Vector;
double cross(Vector a,Vector b)
{
return a.x*b.y-a.y*b.x;
} double dot(Vector a,Vector b)
{
return a.x*b.x+a.y*b.y;
}
double length(Vector a)
{
return sqrt(dot(a,a));
}
double dist(Point a,Point b)
{
return length(a-b);
}
double v_angle(Vector a,Vector b)
{
return acos(dot(a,b)/length(a)/length(b));
} int ConvexHull(Point *p, int n, Point *ch)
{
sort(p, p+n);
n = unique(p, p+n) - p;
int m = 0;
for(int i = 0; i < n; i++)
{
while(m > 1 && dcmp(cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) m--;
ch[m++] = p[i];
}
int k = m;
for(int i = n-2; i >= 0; i--)
{
while(m > k && dcmp(cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) m--;
ch[m++] = p[i];
}
if(n > 1) m--;
return m;
}
Vector rotate(Vector a,double rad)
{
Vector c;
c.x = a.x*cos(rad)-a.y*sin(rad);
c.y = a.x*sin(rad)+a.y*cos(rad);
return c;
}
void get_ocmt(Circle c1,Circle c2,Point &s1, Point &e1,Point &s2,Point &e2)
{
double l = dist(c1.o,c2.o);
double d = fabs(c1.r-c2.r);
double theta = acos(d/l);
//if(dcmp(c1.r-c2.r)>0) swap(c1,c2);
Vector vec = c1.o-c2.o;
vec = vec.trunc(c1.r);
s1 = c1.o+rotate(vec,theta);
s2 = c1.o+vec.rotate(-theta);
vec = vec.trunc(c2.r);
e1 = c2.o+vec.rotate(theta);
e2 = c2.o+vec.rotate(-theta);
}
void get_pc(Circle c, Point p,Point &s1,Point &s2)
{
Vector u = p-c.o; double dist = length(u);
Point v = c.o+u/dist*c.r;
double ang = PI/2-asin(c.r/dist);
s1 = rotate(v-c.o,-ang)+c.o;
s2 = rotate(v-c.o,ang)+c.o;
}
Point p[55*55*55],ch[55*55*55];
int main()
{
//freopen("/home/qitaishui/code/in.txt","r",stdin);
int n,m,pn,chn;
Circle c[MAXN];
Tri tri[MAXN]; while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i = 0; i < n;i++)
{
c[i].o.input();
scanf("%lf",&c[i].r);
}
if(n==1&&m==0)
{
printf("%.6f\n",c[0].len(2*PI));
continue;
}
for(int i = 0; i < m; i++)
for(int j = 0; j < 3; j++)
tri[i].p[j].input();
pn = 0;
for(int i = 0; i < n; i++)
for(int j = i+1; j < n; j++)
{
if(dcmp(c[i].r-c[j].r)>0)
get_ocmt(c[j],c[i],p[pn+1],p[pn],p[pn+3],p[pn+2]);
else
get_ocmt(c[i],c[j],p[pn],p[pn+1],p[pn+2],p[pn+3]);
p[pn].tp = 0,p[pn].id = i;
p[pn+1].tp = 0,p[pn+1].id = j;
p[pn+2].tp = 0,p[pn+2].id = i;
p[pn+3].tp = 0,p[pn+3].id = j;
pn+=4;
}
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
for(int k = 0; k <3; k++)
{
get_pc(c[i],tri[j].p[k],p[pn],p[pn+1]);
p[pn].tp = 0,p[pn].id = i;
p[pn+1].tp = 0,p[pn+1].id = i;
pn+=2;
} for(int j = 0; j < m; j++)
for(int k = 0; k <3; k++)
{
p[pn] = tri[j].p[k];
p[pn].tp = 1, p[pn].id = j;
pn++;
} chn = ConvexHull(p,pn,ch);
//cout<<chn<<endl;
int top=0;
bool flag = 0;
double ans = 0,cir=0;
for(int i = 0; i <chn; i++)
{
if(ch[i].tp==0&&ch[(i+1)%chn].tp==0&&ch[i].id==ch[(i+1)%chn].id)
{
int tmp=ch[i].id;
double ang;
ang = v_angle(ch[i]-c[tmp].o,ch[(i+1)%chn]-c[tmp].o);
if(dcmp(cross(ch[i]-c[tmp].o,ch[(i+1)%chn]-c[tmp].o))<0)
ang = 2*PI-ang;
ans=ans+c[tmp].len(ang);
}
else
ans+=length(ch[i]-ch[(i+1)%chn]);
} printf("%.6f\n",ans);
}
return 0;
}

4667 Building Fence 解题报告的更多相关文章

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

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

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

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

  3. 【LeetCode】276. Paint Fence 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 动态规划 日期 题目地址:https://leetco ...

  4. 洛谷 画栅栏Painting the Fence 解题报告

    P2205 画栅栏Painting the Fence 题目描述 \(Farmer\) \(John\) 想出了一个给牛棚旁的长围墙涂色的好方法.(为了简单起见,我们把围墙看做一维的数轴,每一个单位长 ...

  5. codeforces B. Color the Fence 解题报告

    题目链接:http://codeforces.com/problemset/problem/349/B 题目意思:给定v升的颜料和9个需要花费ad 升的颜料,花费ad 升的颜料意味着得到第d个数字,现 ...

  6. codeforces B.Fence 解题报告

    题目链接:http://codeforces.com/problemset/problem/363/B 题目意思:给定整数n和k,需要从n个数中找出连续的k个数之和最小,输出这连续的k个数中的第一个数 ...

  7. HDU 4667 Building Fence

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

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

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

  9. hdu 4667 Building Fence < 计算几何模板>

    //大白p263 #include <cmath> #include <cstdio> #include <cstring> #include <string ...

随机推荐

  1. UVALive 6257 Chemist's vows

    #include<iostream> #include<string.h> #include<stdio.h> #include<ctype.h> #i ...

  2. elasticsearch ik中文分词器安装

    特殊说明:灰色文字用来辅助理解的. 安装IK中文分词器 我在百度上搜索了下,大多介绍的都是用maven打包下载下来的源码,这种方法也行,但是不够方便,为什么这么说? 首先需要安装maven吧?其次需要 ...

  3. spring---transaction(6)---事务的配置

    1 写在前面 上一篇我们了解到spring的事务的体系.这里我们将结合上篇讲spring事务的配置 2 Spring的三种事务配置形式 2.1 使用TransactionProxyFactoryBea ...

  4. SVN服务端的版本对比及创建仓库时的注意事项

    SVN是一个开放源代码的版本控制系统,分为客户端和服务端.就windows系统而言,客户端通常使用 TortoiseSVN,下载地址:https://tortoisesvn.net/  ,而服务端通常 ...

  5. 【scrapy】使用方法概要(三)(转)

    请初学者作为参考,不建议高手看这个浪费时间] 前两篇大概讲述了scrapy的安装及工作流程.这篇文章主要以一个实例来介绍scrapy的开发流程,本想以教程自带的dirbot作为例子,但感觉大家应该最先 ...

  6. Turtelizer 2 provide JTAG Flash programming and debugging of ARM based boards via USB

    http://www.ethernut.de/en/hardware/turtelizer/ Introducing Turtelizer 2 Overview Turtelizer 2 had be ...

  7. 完整的POM文档内容

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  8. iOS开发里的Bundle是个啥玩意?!

    初学iOS开发的同学,不管是自己写的,还是粘贴的代码,或多或少都写过下面的代码 [[NSBundle mainBundle] pathForResource:@"someFileName&q ...

  9. IOS开发之----代码块的使用(二)

    iOS4引入了一个新特性,支持代码块的使用,这将从根本上改变你的编程方式.代码块是对C语言的一个扩展,因此在Objective-C中完全支持.如果你学过Ruby,Python或Lisp编程语言,那么你 ...

  10. C#编程(八)--------- Main函数

    Main()方法. C#程序是以Main()开始执行的,这个方法必须是类或结构的静态方法,并且其返回类型必须是int或者void. 虽然显示指定public修饰符很常见,但是我们也可以把该方法标记为p ...