Hdu 4667 Building Fence
来源:互联网 发布:js给日期控件赋值 编辑:程序博客网 时间:2024/05/22 05:29
Building Fence
这个题有两种解法:
方法一:将圆均分2000个点,暴力水过
程序简单,好写
精度要求比较高,无从下手的时候可以尝试一下,一旦精度要求比较高不过的可能性比较大...
交c++超时,g++800+ms,表示不理解
const int INF = 1000000000;const double eps = 1e-10;const int MOD = 100000007;const int MAXN = 10000000;const double PI = acos(-1.0);///*************基础***********/inline int dcmp(double x){ if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;}struct Point{ double x, y; Point(double x=0, double y=0):x(x),y(y) { } inline void read() { scanf("%lf%lf", &x, &y); }};typedef vector<Point> Polygon;typedef Point Vector;inline Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }inline Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }inline Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }inline Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }inline bool operator < (const Point& a, const Point& b){ return a.x < b.x || (a.x == b.x && a.y < b.y);}inline bool operator == (const Point& a, const Point &b){ return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;}inline double Dot(Vector A, Vector B){ return A.x*B.x + A.y*B.y;}inline double Length(Vector A){ return sqrt(Dot(A, A));}inline double Angle(Vector A, Vector B){ return acos(Dot(A, B) / Length(A) / Length(B));}inline double angle(Vector v){ return atan2(v.y, v.x);}inline double Cross(Vector A, Vector B){ return A.x*B.y - A.y*B.x;}inline Vector vecunit(Vector x){ return x / Length(x); //单位向量}inline Vector Normal(Vector x){ return Point(-x.y, x.x) / Length(x); //垂直法向量}inline Vector Rotate(Vector A, double rad){ return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));}// 点集凸包// 如果不希望在凸包的边上有输入点,把两个 <= 改成 <// 注意:输入点集会被修改vector<Point> ConvexHull(vector<Point>& p){ // 预处理,删除重复点 sort(p.begin(), p.end()); p.erase(unique(p.begin(), p.end()), p.end()); int n = p.size(); int m = 0; vector<Point> ch(n+1); for(int i = 0; i < n; i++) { while(m > 1 && 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 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--; ch[m++] = p[i]; } if(n > 1) m--; ch.resize(m); return ch;}inline double dist(Point a, Point b){ return Length(a - b);}/************圆************/struct Circle{ Point c; double r; Circle() {} Circle(Point c, double r):c(c), r(r) {} inline Point point(double a) //根据圆心角求点坐标 { return Point(c.x+cos(a)*r, c.y+sin(a)*r); }};vector<Point> p, ans;const double interval = PI / 1000;int main(){// freopen("0.txt", "r", stdin); int N, M, size; Point input; double r, tx, ty, dis, ang; while (~RII(N, M)) { ans.clear(), p.clear(); dis = 0; REP(i, N) { scanf("%lf%lf%lf", &tx, &ty, &r); for (double ang = 0; ang < 2 * PI; ang += interval) { input.x = tx + cos(ang) * r; input.y = ty + sin(ang) * r; p.push_back(input); } } REP(i, M) { input.read(); p.push_back(input); input.read(); p.push_back(input); input.read(); p.push_back(input); } ans = ConvexHull(p); size = ans.size(); REP(i, size - 1) { dis += Length(ans[i] - ans[i + 1]); } dis += dist(ans[size - 1], ans[0]); printf("%.5lf\n", dis); } return 0;}
方法二:
将有可能构成凸包的点计算出来,包括 三角形的顶点,三角形顶点与各个圆的切点,任意两个圆的切点
然后计算凸包即可
有两个要注意的地方,第一是求凸包边长时候,需要判断一下当前计算的两个点是否在同一个圆上,若是则需要计算圆弧长度
第二是只有一个圆的时候需要特判
const int INF = 0x3f3f3f3f;const double eps = 1e-10;const int MOD = 100000007;const int MAXN = 1000010;const double PI = acos(-1.0);///*************基础***********/double torad(double deg){ return deg / 180 * PI;}inline int dcmp(double x){ if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;}struct Point{ double x, y; Point(double x=0, double y=0):x(x),y(y) { } inline void read() { scanf("%lf%lf", &x, &y); }};typedef vector<Point> Polygon;typedef Point Vector;inline Vector operator + (Vector A, Vector B){ return Vector(A.x+B.x, A.y+B.y);}inline Vector operator - (Point A, Point B){ return Vector(A.x-B.x, A.y-B.y);}inline Vector operator * (Vector A, double p){ return Vector(A.x*p, A.y*p);}inline Vector operator / (Vector A, double p){ return Vector(A.x/p, A.y/p);}inline bool operator < (Point a, Point b){ return a.x < b.x || (a.x == b.x && a.y < b.y);}inline bool operator == (Point a, Point b){ return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;}inline double Dot(Vector A, Vector B){ return A.x*B.x + A.y*B.y;}inline double Length(Vector A){ return sqrt(Dot(A, A));}inline double Angle(Vector A, Vector B){ return acos(Dot(A, B) / Length(A) / Length(B));}inline double angle(Vector v){ return atan2(v.y, v.x);}inline double Cross(Vector A, Vector B){ return A.x*B.y - A.y*B.x;}inline Vector Unit(Vector x){ return x / Length(x); //单位向量}inline Vector Normal(Vector x){ return Point(-x.y, x.x) / Length(x); //垂直法向量}inline Vector Rotate(Vector A, double rad){ return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));}inline double Area2(Point A, Point B, Point C){ return Cross(B-A, C-A);}template <class T> T sqr(T x){ return x * x ;}// 点集凸包// 如果不希望在凸包的边上有输入点,把两个 <= 改成 <// 注意:输入点集会被修改vector<Point> ConvexHull(vector<Point>& p){ // 预处理,删除重复点 sort(p.begin(), p.end()); p.erase(unique(p.begin(), p.end()), p.end()); int n = p.size(); int m = 0; vector<Point> ch(n+1); for(int i = 0; i < n; i++) { while(m > 1 && 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 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--; ch[m++] = p[i]; } if(n > 1) m--; ch.resize(m); return ch;}inline double dist(Point a, Point b){ return Length(a - b);}/************圆************/struct Circle{ Point c; double r; Circle() {} Circle(Point c, double r):c(c), r(r) {} inline Point point(double a) //根据圆心角求点坐标 { return Point(c.x+cos(a)*r, c.y+sin(a)*r); } inline void read() { scanf("%lf%lf%lf", &c.x, &c.y, &r); }};//求a点到b点(逆时针)在的圆上的圆弧长度double DisOnCircle(Point a, Point b, Circle C){ double ang1 = angle(a - C.c); double ang2 = angle(b - C.c); if (ang2 < ang1) ang2 += 2 * PI; return C.r * (ang2 - ang1);}// 过点p到圆C的切点int getTangentPoints(Point p, Circle C, vector<Point>& v){ Vector u = C.c - p; double dist = Length(u); if(dist < C.r) return 0; else if(dcmp(dist - C.r) == 0) // p在圆上,只有一条切线 { v.push_back(p); return 1; } else { double ang = asin(C.r / dist); double d = sqrt(dist * dist - C.r * C.r); v.push_back(p + Unit(Rotate(u, -ang)) * d); v.push_back(p + Unit(Rotate(u, +ang)) * d); return 2; }}//圆A与圆B的切点void getTangentPoints(Circle A, Circle B, vector<Point>& a){ if (A.r < B.r) swap(A, B); ///**************************** int d2 = sqr(A.c.x - B.c.x) + sqr(A.c.y - B.c.y); int rdiff = A.r - B.r, rsum = A.r + B.r; if (d2 < rdiff * rdiff) return; //内含 ///*************************************** double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x); if (d2 == 0 && A.r == B.r) return; //无线多条切线 if (d2 == rdiff * rdiff) //内切, 1条切线 { ///********************** a.push_back(A.point(base)); a.push_back(B.point(base)); return; } //有外公切线 double ang = acos((A.r - B.r) / sqrt(d2 * 1.0)); a.push_back(A.point(base + ang)); a.push_back(B.point(base + ang)); a.push_back(A.point(base - ang)); a.push_back(B.point(base - ang)); if (d2 == rsum * rsum) //一条内公切线 { a.push_back(A.point(base)); a.push_back(B.point(PI + base)); } else if (d2 > rsum * rsum) //两条内公切线 { double ang = acos((A.r + B.r) / sqrt(d2 * 1.0)); a.push_back(A.point(base + ang)); a.push_back(B.point(PI + base + ang)); a.push_back(A.point(base - ang)); a.push_back(B.point(PI + base - ang)); }}inline bool OnCircle(Point x, Circle c){ return dcmp(c.r - Length(c.c - x)) == 0;}Circle C[60];Point P[160];vector<Point> ch, sol;double t1, t2;int main(){ int a, b; while (~RII(a, b)) { ch.clear(), sol.clear(); REP(i, a) C[i].read(); b *= 3; REP(i, b) { P[i].read(); sol.push_back(P[i]); } REP(i, b) REP(j, a) { getTangentPoints(P[i], C[j], sol); } FF(i, 0, a) FF(j, i + 1, a) { getTangentPoints(C[i], C[j], sol); } ch = ConvexHull(sol); double ans = 0; int len = ch.size(); REP(i, len) { REP(j, a) { if (OnCircle(ch[i], C[j]) && OnCircle(ch[(i + 1) % len], C[j])) { ans += DisOnCircle(ch[i], ch[(i + 1) % len], C[j]); goto end; } } ans += dist(ch[i], ch[(i + 1) % len]); end:; } if (a == 1 && b == 0) ans += 2 * PI * C[0].r; printf("%.5lf\n", ans); } return 0;}
- HDU 4667 Building Fence
- hdu 4667 Building Fence
- HDU 4667 Building Fence
- Hdu 4667 Building Fence
- HDU 4667 Building Fence 解题报告
- HDU 4667 Building Fence(求凸包的周长)
- hdu 4667 Building Fence(几何)
- HDU 4667 Building Fence(求凸包的周长)
- Building Fence hdu 凸包
- 2013 多校第七场 hdu 4667 Building Fence
- hdu 4667 Building Fence(二维凸包 Graham)
- 2013 多校第七场 hdu 4667 Building Fence(计算几何、凸包)
- HDU4667 Building Fence(凸包)
- Building A Fence, usaco 2008 Oct
- 【bzoj1600】【USACO2008 Oct】Building A Fence 建造栅栏
- HDU-4584-Building bridges
- hdu 2818 Building Block
- HDU 4584 Building bridges
- FATFS学习
- UVA 10277 Boastin' Red Socks
- java 集合框架-韩顺平视频截图笔记
- 在javascript代码中获得使用struts2框架传回来的数据
- Unsupported major.minor version 51.0解决
- Hdu 4667 Building Fence
- windows server 2003 安装IIS 6.0 + 部署asp网站
- nginx 自动调试脚本
- CTP5自定义验证
- 在linux上用dd命令实现ghost功能
- java常用转义字符
- 大话设计模式--解释器模式 interpreter -- C++实现实例
- Spring AOP应该用到Spring MVC上不起作用?怎么才能让aop起作用
- CF World Football Cup