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

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

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

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

#include<algorithm>
#include<iostream>
#include<cstring>
#include<fstream>
#include<sstream>
#include<vector>
#include<string>
#include<cstdio>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<map>
#include<set>
#define FF(i, a, b) for(int i=a; i<b; i++)
#define FD(i, a, b) for(int i=a; i>=b; i--)
#define REP(i, n) for(int i=0; i<n; i++)
#define CLR(a, b) memset(a, b, sizeof(a))
#define LL long long
#define PB push_back
#define eps 1e-10
#define debug puts("**debug**")
using namespace std; const double PI = acos(-1);
const double INF = 1e20;
const int maxn = 11111;
struct Point
{
double x, y;
Point (double x=0, double y=0):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); }
}; 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;
}
}; 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; }
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<Point>& 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<Point> sol;
Circle C[30];
Point s, t;
bool vis[maxn]; bool check(Point A, Point B)
{
vector<Point> 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<Edge> edges;
vector<int> G[maxn];
bool done[maxn];
double d[maxn]; double dij(int s, int t, int n)
{
priority_queue<Heap> 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;
}

hdu 4063 Aircraft(计算几何+最短路)的更多相关文章

  1. 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 ...

  2. HDU 4063 Aircraft --几何,最短路

    题意: 给一些圆,要求从第一个圆的圆心走到最后一个圆的圆心,中间路径必须在某个圆内,求最短路径的长度. 解法: 易知要保持在圆内且路径最短,走两圆相交的点能使路径尽量短,所以我们找出所有的两圆相交的点 ...

  3. hdu 4063 Aircraft (Geometry + SP)

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

  4. HDU 4998 Rotate (计算几何)

    HDU 4998 Rotate (计算几何) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4998 Description Noting is more ...

  5. hdu 4643 GSM 计算几何 - 点线关系

    /* hdu 4643 GSM 计算几何 - 点线关系 N个城市,任意两个城市之间都有沿他们之间直线的铁路 M个基站 问从城市A到城市B需要切换几次基站 当从基站a切换到基站b时,切换的地点就是ab的 ...

  6. HDU 4606 Occupy Cities (计算几何+最短路+最小路径覆盖)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题目:给出n个城市需要去占领,有m条线段是障碍物, ...

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

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

  8. HDU 4606 Occupy Cities (计算几何+最短路+二分+最小路径覆盖)

    Occupy Cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

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

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

随机推荐

  1. [HDU 3336]Count the String[kmp][DP]

    题意: 求一个字符串的所有前缀串的匹配次数之和. 思路: 首先仔细思考: 前缀串匹配. n个位置, 以每一个位置为结尾, 就可以得到对应的一个前缀串. 对于一个前缀串, 我们需要计算它的匹配次数. k ...

  2. perl5 第十二章 Perl5中的引用/指针

    第十二章 Perl5中的引用/指针 by flamephoenix 一.引用简介二.使用引用三.使用反斜线(\)操作符四.引用和数组五.多维数组六.子程序的引用  子程序模板七.数组与子程序八.文件句 ...

  3. android 构建数据库SQLite

    1.首先我们需要一个空白的eclipse android工程 2.然后修改AndroidManifest.xml 在<application></application>标签里 ...

  4. python Unicode转ascii码的一种方法

    缘起 看到这样的数据:Marek Čech.Beniardá怎样变成相对应的ascii码呢 解决 import unicodedata s = u"Marek Čech" #(u表 ...

  5. iOS中怎样加入自己定义的字体

    苹果对于开发,确实在细节方面下了非常大的功夫,只是不管一个平台下多大的功夫,仍然会有些需求是无法涵盖的.比方字体吧. 我们的应用为了能更加个性化.会须要不同的字体.有时候有些字体是非常特殊的.甚至是购 ...

  6. Sublime 操作技巧

    吐槽一下:刚下载的subime不是等宽字体,空格.表达.字母i什么的都很窄,看着不方便: 根据网上说的换成等宽字体,试了好多种字体,字体变了.但宽度没变. 然后有装了soda,和相应的color-th ...

  7. 利用jQuery获取数据,JSONP

    最近工作用到了跨域请求,所以此文就有了,概念网上都有,就不细说了,直接来了. 看了一篇文章,说的是通过扩展让ASP.NET Web API支持JSONP,jsonp网上有很多的教程,js代码部分基本和 ...

  8. Axure使用

    (一)  Axure rp的界面 1-主菜单工具栏 大部分类似office软件,不做详细解释,鼠标移到按钮上都有对应的提示. 2-主操作界面 绘制产品原型的操作区域,所有的用到的元件都拖到该区域. 3 ...

  9. Java学习03

    Java学习03 1.java面试一些问题 一.什么是变量 变量是指在程序执行期间可变的数据.类中的变量是用来表示累的属性的,在编程过程中,可以对变量的值进行修改.变量通常是可变的,即值是变化的 二. ...

  10. php 用户访问菜单页面,必须登录,判断用户是否登录

    <pre name="code" class="python"># 本节课大纲: 一.空模块和空操作 1.空操作 function _empty($ ...