博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu 4063 Aircraft(计算几何+最短路)
阅读量:6002 次
发布时间:2019-06-20

本文共 5440 字,大约阅读时间需要 18 分钟。

不说了。。。说多了都是泪。。。从昨天下午一直wa到现在,直到刚刚才让人帮我找到所谓的“bug”,其实也算不上bug。。。

这个题的思路就是:找出平面上的所有点:所有圆的交点以及所有圆的圆心。然后依次判断两点是否连通,连通的话两点距离便是其欧几里得距离。这样建完图之后直接跑s->t最短路就行了。。

两点连通?也就是说这两点连成的线段,一直在圆内,任意圆都行。如何判断呢,求出该线段与所有圆的所有交点,排序后将其分段,依次判断每一段是否在任意圆内。这个么,在分段后,判断每一段的中点是否在圆内就行了。

这题并不是很难啊?我的bug在哪??刚开始我是将所有圆的圆心都加到平面点集中,wa到死有木有。。。刚刚改了改,只加第一个跟最后一个圆的圆心。。立A。。为什么?

 

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define FF(i, a, b) for(int i=a; i
=b; i--)#define REP(i, n) for(int i=0; i
T sqr(T x) { return x * x;}Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }Vector operator - (Vector A, Vector B) { return Vector(A.x - B.x, A.y - B.y); }Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }bool operator < (const Point& a, const Point& b) { return a.x < b.x || (a.x == b.x && a.y < b.y); }bool operator >= (const Point& a, const Point& b) { return a.x >= b.x && a.y >= b.y; }bool operator <= (const Point& a, const Point& b) { return a.x <= b.x && a.y <= b.y; }int dcmp(double x){ if(fabs(x) < eps) return 0; return x < 0 ? -1 : 1;}bool operator == (const Point& a, const Point& b){ return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;}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 Angel(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); }double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }Vector vecunit(Vector x){ return x / Length(x);}Vector normal(Vector x) { return Point(-x.y, x.x) / Length(x);}double angel(Vector v) { return atan2(v.y, v.x); }bool OnSegment(Point p, Point a1, Point a2){ return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;}bool InCircle(Point x, Circle c) { return dcmp(sqr(c.r) - sqr(Length(c.c - x))) > 0;}double DistanceToSeg(Point p, Point a, Point b){ if(a == b) return Length(p-a); Vector v1 = b-a, v2 = p-a, v3 = p-b; if(dcmp(Dot(v1, v2)) < 0) return Length(v2); if(dcmp(Dot(v1, v3)) > 0) return Length(v3); return fabs(Cross(v1, v2)) / Length(v1);}void getLineABC(Point A, Point B, double& a, double& b, double& c){ a = A.y-B.y, b = B.x-A.x, c = A.x*B.y-A.y*B.x;}Point GetIntersection(Line a, Line b){ Vector u = a.p-b.p; double t = Cross(b.v, u) / Cross(a.v, b.v); return a.p + a.v*t;}int getCCintersection(Circle C1, Circle C2, vector
& sol){ double d = Length(C1.c - C2.c); if(dcmp(d) == 0) { if(dcmp(C1.r - C2.r) == 0) return -1; return 0; } if(dcmp(C1.r + C2.r - d) < 0) return 0; if(dcmp(fabs(C1.r - C2.r) - d) > 0) return 0; double a = angel(C2.c - C1.c); double da = acos((sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2*C1.r*d)); Point p1 = C1.point(a-da), p2 = C1.point(a+da); sol.PB(p1); if(p1 == p2) return 1; sol.PB(p2); return 2;}int getSegCircleIntersection(Line L, Circle C, Point* sol){ Vector nor = normal(L.v); Line pl = Line(C.c, nor); Point ip = GetIntersection(pl, L); double dis = Length(ip - C.c); if (dcmp(dis - C.r) > 0) return 0; Point dxy = vecunit(L.v) * sqrt(sqr(C.r) - sqr(dis)); int ret = 0; sol[ret] = ip + dxy; if (OnSegment(sol[ret], L.p, L.point(1))) ret++; sol[ret] = ip - dxy; if (OnSegment(sol[ret], L.p, L.point(1))) ret++; return ret;}int T, n;vector
sol;Circle C[30];Point s, t;bool vis[maxn];bool check(Point A, Point B){ vector
gank; gank.PB(A); gank.PB(B); Point roshan[2]; REP(i, n) { //线段ab与所有圆的交点 int m = getSegCircleIntersection(Line(A, B-A), C[i], roshan); if(m == 1) gank.PB(roshan[0]); if(m == 2) gank.PB(roshan[0]), gank.PB(roshan[1]); } sort(gank.begin(), gank.end()); int nc = gank.size(); REP(i, nc-1) { Point mid = (gank[i] + gank[i+1]) / 2.0; //重点跳过 if(mid == gank[i]) continue; bool flag = 0; REP(j, n) if(InCircle(mid, C[j]))//分段中点是否被任意圆覆盖 { flag = 1; break; } if(!flag) return false; } return true;}struct Heap{ double d; int u; bool operator < (const Heap& rhs) const { return dcmp(d-rhs.d) > 0; }};struct Edge{ int from, to; double dist;};vector
edges;vector
G[maxn];bool done[maxn];double d[maxn];double dij(int s, int t, int n){ priority_queue
q; q.push((Heap){0.0, s}); REP(i, n) d[i] = INF; d[s] = 0.0; CLR(done, 0); while(!q.empty()) { Heap x = q.top(); q.pop(); int u = x.u, nc = G[u].size(); if(done[u]) continue; done[u] = 1; REP(i, nc) { Edge& e = edges[G[u][i]]; if(dcmp(d[e.to]-d[u]-e.dist) > 0) { d[e.to] = d[u] + e.dist; q.push((Heap){d[e.to], e.to}); } } } return d[t];}void add(int from, int to, double dist){ edges.PB((Edge){from, to, dist}); edges.PB((Edge){to, from, dist}); int nc = edges.size(); G[from].PB(nc-2); G[to].PB(nc-1);}void init(){ REP(i, maxn) G[i].clear(); sol.clear(); edges.clear();}int main(){ scanf("%d", &T); FF(kase, 1, T+1) { init(); scanf("%d", &n); //sol存平面上所有点 REP(i, n) { scanf("%lf%lf%lf", &C[i].c.x, &C[i].c.y, &C[i].r); if(i == 0 || i == n-1) sol.PB(C[i].c);//加入圆心.... } REP(i, n) FF(j, i+1, n) getCCintersection(C[i], C[j], sol);//所有圆的交点 //去重 sort(sol.begin(), sol.end()); int nc = unique(sol.begin(), sol.end()) - sol.begin(); int s, t; REP(i, nc) { FF(j, i+1, nc) if(check(sol[i], sol[j])) //判断两点是否连通 add(i, j, Length(sol[i] - sol[j])); //最短路的起始点 if(sol[i] == C[0].c) s = i; if(sol[i] == C[n-1].c) t = i; } double ans = dij(s, t, nc); printf("Case %d: ", kase); if(dcmp(ans-INF) >= 0) puts("No such path."); else printf("%.4lf\n", ans); } return 0;}

 

 

转载地址:http://dndmx.baihongyu.com/

你可能感兴趣的文章
【YUM】第三方yum源rpmforge
查看>>
IOS(CGGeometry)几何类方法总结
查看>>
一个通用并发对象池的实现
查看>>
才知道系列之GroupOn
查看>>
⑲云上场景:超级减肥王,基于OSS的高效存储实践
查看>>
linux kswapd浅析
查看>>
变更 Linux、Ubuntu 时区、时间
查看>>
高仿QQ空间 侧滑Menu效果且换肤功能《IT蓝豹》
查看>>
mac的git的21个客户端
查看>>
Django之form表单实例
查看>>
python 笔记 之带参数的装饰器
查看>>
Spring Cloud自定义引导属性源
查看>>
OSChina 周日乱弹 ——程序员怎么攒钱买房子!(励志、温情)
查看>>
OSChina 周三乱弹 —— 总觉得路过是 VIVO 大酒店
查看>>
OSChina 周四乱弹 —— 未来人类的知识宝库
查看>>
mysql树状数据的数据库设计
查看>>
JavaScript快速入门
查看>>
Intger 自动装拆箱
查看>>
html中a连接触发表单提交
查看>>
Linux网卡名改eth0方法
查看>>