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.已知两 ...
随机推荐
- linux shell 编程
1,获取命令执行的结果,字符串拼接(脚本最常使用的功能) cmd_result=$(date +%Y%b%d) //使用变量获取命令执行的结果 或者 cmd_result=`date ...
- StackOverflow Update: 560M Pageviews A Month, 25 Servers, And It's All About Performance
http://highscalability.com/blog/2014/7/21/stackoverflow-update-560m-pageviews-a-month-25-servers-and ...
- Java学习笔记之_JDBC
JDBC简介 1.SUN公司为了简化,统一数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC 2.数据库驱动 3.JDBC全称为:JAVA DataBase Commectivity(j ...
- AloneJs.albumBox() —— 相册对话框
一.引用 <link href="https://cdn.suziyun.com/alonejs.min.css" rel="stylesheet" /& ...
- HillStone上网认证客户端
公司上网认证服务器从原来网康变更成山石(HillStone),原来网康是有认证客户端的,运行在系统托盘区,现在的Hillstone是通过网页页面认证的,要上网,这个认证页面就需要一直打开在那里.碰到异 ...
- C标准库<assert.h>实现
本文地址:http://www.cnblogs.com/archimedes/p/c-library-assert.html,转载请注明源地址. 1.背景知识 头文件<assert.h>唯 ...
- 简明 Vim 练级攻略(转)
原文:http://coolshell.cn/articles/5426.html vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会 ...
- 【转】IOS中的release和nil
nil和release的作用: nil就是把一个对象的指针置为空,只是切断了指针与内存中对象的联系:而release才是真正通知内存释放这个对象. 所以nil并没有释放内存,只有release才回真正 ...
- NSDictionary和NSMutableDictionary
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { ...
- Java集合 之 Queue集合
什么是Queue集合? 答:Queue用于模拟队列这种数据结构.队列通常是指“先进先出(FIFO)”的容器.队列的头部保存在队列中存放时间最长的元素,尾部保存存放时间最短的元素.新元素插入到队列的尾部 ...