HDU 4063 Aircraft --几何,最短路
题意: 给一些圆,要求从第一个圆的圆心走到最后一个圆的圆心,中间路径必须在某个圆内,求最短路径的长度。
解法: 易知要保持在圆内且路径最短,走两圆相交的点能使路径尽量短,所以我们找出所有的两圆相交的点,再加上起点和终点,放到一个容器中,去重后,判断每两点之间的线段是否都在圆内,如果是则建边,建完所有的边后跑一个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 --几何,最短路的更多相关文章
- hdu 4063 Aircraft(计算几何+最短路)
不说了...说多了都是泪...从昨天下午一直wa到现在,直到刚刚才让人帮我找到所谓的“bug”,其实也算不上bug... 这个题的思路就是:找出平面上的所有点:所有圆的交点以及所有圆的圆心.然后依次判 ...
- 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 ...
- hdu 4063 Aircraft (Geometry + SP)
Problem - 4063 几何加简单最短路. 题意是给出若干圆的圆心以及半径,求出从给出的起点到终点的最短路径的长度,可以移动的区域是圆覆盖到的任意一个位置. 做法是这样的,对圆两两求交点,用这些 ...
- HDU 4063 线段与圆相交+最短路
Aircraft Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...
- hdu 1245 Saving James Bond 策画几何+最短路 最短路求步数最少的路径
#include<stdio.h> #include<string.h> #include<math.h> #define inf 0x3fffffff #defi ...
- HDU 5294 Tricks Device 最短路+最大流
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5294 题意: 给你个无向图: 1.求最少删除几条边就能破坏节点1到节点n的最短路径, 2.最多能删除 ...
- 2017多校第10场 HDU 6181 Two Paths 次短路
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6181 题意:给一个图,求出次短路. 解法:我之前的模板不能解决这种图,就是最短路和次短路相等的情况,证 ...
- HDU 5889 Barricade(最短路+最小割)
http://acm.hdu.edu.cn/showproblem.php?pid=5889 题意: 给出一个图,帝国将军位于1处,敌军位于n处,敌军会选择最短路到达1点.现在帝国将军要在路径上放置障 ...
- hdu 5521 Meeting(最短路)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5521 题意:有1-n共n个点,给出m个块(完全图),并知道块内各点之间互相到达花费时间均为ti.已知两 ...
随机推荐
- mysql zip install
1.Question Description: 1.1 version: mysql-5.7.11-64 1.2 form: zip file 1.3 >mysqld --install (su ...
- [翻译]:SQL死锁-为什么会出现死锁
下面这篇对理解死锁非常重要,首先死锁是如何产生的我们要清楚. We already know why blocking occurs in the system and howto detect an ...
- access的逻辑类型
Alter TABLE [表名] ADD [新增字段] BOOLEAN或者Alter TABLE [表名] ADD [新增字段] YESNO 或者Alter TABLE [表名] ADD [新增字段] ...
- 如何利用ArcGIS Engine接口实现打开Raster Catalog中的某一幅指定的影像?
将IRasterCatalog转化为ITable,然后通过ITable.GetRow返回指定索引的IRow,将IRow转为IRasterCatalogItem,进而获取IRasterCatalogIt ...
- ubuntu14.0安装arm-linux-gcc交叉编译环境
1.下载文件: 安装包:arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz 下载地址 http://pan.baidu.com/s/1pJwQ6Sj 2.开始安装(建议大 ...
- MQTT for UWP
老规矩,先简单介绍下MQTT: MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分.该协 ...
- 手把手搭建自己的android环境
最近想学习安卓,不过国内实在被墙的厉害,真是"万里安装只被墙".安装的过程中也出现了几个问题.所以记录下来,免得自己下次再次安装的时候又来重蹈覆辙. 以下的问题也是按照出现的顺序排 ...
- UISegmentedControl的使用
#import "SegmentedControlTestViewController.h" @implementation SegmentedControlTestViewCon ...
- Swift开发第五篇——四个知识点(Struct Mutable方法&Tuple&autoclosure&Optional Chain)
本篇分三部分: 一.Struct Mutable方法 二.多元组(Tuple) 的使用 三.autoclosure 的使用 四.Optional Chain 的使用 一.Struct Mutable方 ...
- Swift面向对象基础(上)——Swift中的枚举
Swift中枚举 学习笔记来自<极客学院> import Foundation /**********1*Swift定义枚举的语法格式*************/ /* enum 枚举名 ...