题意: 给一些圆,要求从第一个圆的圆心走到最后一个圆的圆心,中间路径必须在某个圆内,求最短路径的长度。

解法: 易知要保持在圆内且路径最短,走两圆相交的点能使路径尽量短,所以我们找出所有的两圆相交的点,再加上起点和终点,放到一个容器中,去重后,判断每两点之间的线段是否都在圆内,如果是则建边,建完所有的边后跑一个SPFA即可得出最短路。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#define Mod 1000000007
#define eps 1e-8
using namespace std;
#define N 100017 struct Point{
double x,y;
Point(double x=, double y=):x(x),y(y) {}
};
typedef Point Vector;
struct Circle{
Point c;
double r;
Circle(){}
Circle(Point c,double r):c(c),r(r) {}
Point point(double a) { return Point(c.x + cos(a)*r, c.y + sin(a)*r); }
void input() { scanf("%lf%lf%lf",&c.x,&c.y,&r); }
};
struct Line{
Point p;
Vector v;
double ang;
Line(){}
Line(Point p, Vector v):p(p),v(v) { ang = atan2(v.y,v.x); }
Point point(double t) { return Point(p.x + t*v.x, p.y + t*v.y); }
bool operator < (const Line &L)const { return ang < L.ang; }
};
int dcmp(double x) {
if(x < -eps) return -;
if(x > eps) return ;
return ;
}
template <class T> 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; }
bool operator == (const Point& a, const Point& b) { return dcmp(a.x-b.x) == && dcmp(a.y-b.y) == ; }
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 Angle(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 VectorUnit(Vector x){ return x / Length(x);}
Vector Normal(Vector x) { return Point(-x.y, x.x) / Length(x);}
double angle(Vector v) { return atan2(v.y, v.x); } bool OnSegment(Point P, Point A, Point B) {
return dcmp(Cross(A-P,B-P)) == && dcmp(Dot(A-P,B-P)) < ;
}
bool InCircle(Point x, Circle c) { return dcmp(c.r - Length(c.c-x)) > ; } //not in border
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)) < ) return Length(v2);
if(dcmp(Dot(v1, v3)) > ) return Length(v3);
return fabs(Cross(v1, v2)) / Length(v1);
}
Point GetLineIntersection(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 GetCircleCircleIntersection(Circle C1, Circle C2, vector<Point>& sol) //return 交点个数
{
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); //向量C1C2的极角
double da = acos((sqr(C1.r) + sqr(d) - sqr(C2.r)) / (*C1.r*d)); //C1C2到C1P1的极角 Point p1 = C1.point(a-da), p2 = C1.point(a+da);
sol.push_back(p1);
if(p1 == p2) return ;
sol.push_back(p2);
return ;
}
int GetSegCircleIntersection(Line L, Circle C, Point* sol)
{
Vector Noml = Normal(L.v);
Line PL = Line(C.c, Noml);
Point IP = GetLineIntersection(PL, L); //弦的中点
double Dis = Length(IP - C.c);
if(dcmp(Dis-C.r) > ) return ; //在圆外
Vector HalfChord = VectorUnit(L.v)*sqrt(sqr(C.r)-sqr(Dis));
int ind = ;
sol[ind] = IP + HalfChord;
if(OnSegment(sol[ind],L.p,L.point())) ind++;
sol[ind] = IP - HalfChord;
if(OnSegment(sol[ind],L.p,L.point())) ind++;
return ind;
} //data segment
vector<Point> sol;
Circle C[];
double dis[];
vector<pair<int,double> > G[];
int n,vis[],S,E;
//data ends bool CheckSegInCircle(Point A, Point B){
int i,j;
vector<Point> now;
now.push_back(A), now.push_back(B);
Point inter[];
for(i=;i<=n;i++) {
int m = GetSegCircleIntersection(Line(A,B-A),C[i],inter);
for(j=;j<=m;j++) now.push_back(inter[j-]);
}
sort(now.begin(), now.end());
int sz = now.size();
for(i=;i<sz-;i++) {
Point mid = (now[i] + now[i+])/2.0;
if(mid == now[i]) continue;
for(j=;j<=n;j++)
if(InCircle(mid,C[j]))
break;
if(j == n+) return false;
}
return true;
} void SPFA(int n)
{
for(int i=;i<=n;i++) dis[i] = Mod;
memset(vis,,sizeof(vis));
dis[S] = , vis[S] = ;
queue<int> q;
q.push(S);
while(!q.empty())
{
int u = q.front();
q.pop(); vis[u] = ;
for(int i=;i<G[u].size();i++)
{
int v = G[u][i].first;
double w = G[u][i].second;
if(dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
if(!vis[v]) vis[v] = , q.push(v);
}
}
}
} int main()
{
int t,cs = ,i,j;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
sol.clear();
for(i=;i<=;i++) G[i].clear();
C[].input(), sol.push_back(C[].c);
for(i=;i<n;i++) C[i].input();
C[n].input(), sol.push_back(C[n].c);
for(i=;i<=n;i++)
for(j=i+;j<=n;j++)
GetCircleCircleIntersection(C[i],C[j],sol);
sort(sol.begin(), sol.end());
int ind = unique(sol.begin(), sol.end()) - sol.begin();
for(i=;i<ind;i++)
{
for(j=i+;j<ind;j++)
{
if(CheckSegInCircle(sol[i],sol[j]))
{
G[i].push_back(make_pair(j,Length(sol[i]-sol[j])));
G[j].push_back(make_pair(i,Length(sol[i]-sol[j])));
}
}
if(sol[i] == C[].c) S = i;
if(sol[i] == C[n].c) E = i;
}
SPFA(ind);
printf("Case %d: ",cs++);
if(dcmp(dis[E]-Mod) >= ) puts("No such path.");
else printf("%.4f\n",dis[E]);
}
return ;
}

HDU 4063 Aircraft --几何,最短路的更多相关文章

  1. hdu 4063 Aircraft(计算几何+最短路)

    不说了...说多了都是泪...从昨天下午一直wa到现在,直到刚刚才让人帮我找到所谓的“bug”,其实也算不上bug... 这个题的思路就是:找出平面上的所有点:所有圆的交点以及所有圆的圆心.然后依次判 ...

  2. HDU 4063 Aircraft(计算几何)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4063 Description You are playing a flying game. In th ...

  3. hdu 4063 Aircraft (Geometry + SP)

    Problem - 4063 几何加简单最短路. 题意是给出若干圆的圆心以及半径,求出从给出的起点到终点的最短路径的长度,可以移动的区域是圆覆盖到的任意一个位置. 做法是这样的,对圆两两求交点,用这些 ...

  4. HDU 4063 线段与圆相交+最短路

    Aircraft Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  5. hdu 1245 Saving James Bond 策画几何+最短路 最短路求步数最少的路径

    #include<stdio.h> #include<string.h> #include<math.h> #define inf 0x3fffffff #defi ...

  6. HDU 5294 Tricks Device 最短路+最大流

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5294 题意: 给你个无向图: 1.求最少删除几条边就能破坏节点1到节点n的最短路径, 2.最多能删除 ...

  7. 2017多校第10场 HDU 6181 Two Paths 次短路

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6181 题意:给一个图,求出次短路. 解法:我之前的模板不能解决这种图,就是最短路和次短路相等的情况,证 ...

  8. HDU 5889 Barricade(最短路+最小割)

    http://acm.hdu.edu.cn/showproblem.php?pid=5889 题意: 给出一个图,帝国将军位于1处,敌军位于n处,敌军会选择最短路到达1点.现在帝国将军要在路径上放置障 ...

  9. hdu 5521 Meeting(最短路)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5521 题意:有1-n共n个点,给出m个块(完全图),并知道块内各点之间互相到达花费时间均为ti.已知两 ...

随机推荐

  1. python,python3

    当下主流的Linux发行版都集成了python2,直接在终端输入$python就可进入交互式解释器,或者输入$python3进入python3的解释器,当然,也可以使用这个解释器直接翻译一个pytho ...

  2. 数组json格式的字符串 转 list<Bean>

    1.  字符串形式: [ { "userid": "admin", "name": "admin", "pas ...

  3. 【poj 3167】Cow Patterns(字符串--KMP匹配+数据结构--树状数组)

    题意:给2个数字序列 a 和 b ,问按从小到达排序后,a中的哪些子串与b的名次匹配. a 的长度 N≤100,000,b的长度 M≤25,000,数字的大小 K≤25. 解法:[思考]1.X 暴力. ...

  4. [Architecture Design] CLK Architecture

    CLK.Prototype.Architecture 最近找数据,看到了博客园在不久之前,办了一个架构分享的活动:.Net项目分层与文件夹结构大全.看完之后觉得获益良多,接着也忍不住手痒,开始整理属于 ...

  5. FEE Development Essentials

    FEE Development Essentials JS Basic function call() and apply() func1.bind(thisObj,arg1...argn) Cust ...

  6. ASP.NET MVC 微信公共平台开发之验证消息的真实性

    ASP.NET MVC 微信公共平台开发 验证消息的真实性 在MVC Controller所在项目中添加过滤器,在过滤器中重写 public override void OnActionExecuti ...

  7. ASP.NET数据绑定技术

    1.DataBinder.Eval()方法 DataBinder.Eval()方法是ASP.NET框架支持的一个静态方法,用来计算Late_Bound(后期绑定)数据绑定表达式,并随时将结果转换为字符 ...

  8. C安全编码--数组

    建议和规则 建议: 理解数组的工作方式 获取数组的长度时不要对指针应用sizeof操作符 显示地指定数组的边界,即使它已经由初始化值列表隐式地指定 规则: 保证数组索引位于合法的范围内 在所有源文件中 ...

  9. 内存管理2(主讲MRR)

    内存管理2 我们讨论过properties 后,所有的内存管理系统都是通过控制所有对象的生命周期来减少内存的占用.iOS和OS X应用程序完成这些是通过对象拥有者来实现的,它保证了只要对象使用就会存在 ...

  10. 简明 Vim 练级攻略(转)

    原文:http://coolshell.cn/articles/5426.html vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会 ...