HDU 4063 线段与圆相交+最短路
Aircraft
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 980 Accepted Submission(s): 228
In the game, player controls an aircraft in a 2D-space.
The mission is to drive the craft from starting point to terminal point.
The craft needs wireless signal to move.
A number of devices are placed in the 2D-space, spreading signal.
For a device Di, it has a signal radius -- Ri.
When the distance between the craft and Di is shorter or equal to Ri, it(the craft) gets Di's wireless signal.
Now you need to tell me the shortest path from starting point to terminal point.
The rest of the test file contains T blocks.
Each block starts with an integer n, followed by n devices given as (xi, yi, Ri).
(xi, yi) is position of Di, and Ri is the radius of its signal range.
The first point is the starting point.
The last point is the terminal point.
T <= 25;
2 <= n <= 20 for most cases;
20 < n <= 25 for several cases, completely random generated.
-1000 <= xi, yi <= 1000 , 1 <= ri <= 1000.
All are integers.
Otherwise, output a float number, correct the result to 4 decimal places.(as shown in the sample output)
2 2 0 0 1 2 0 1 2 0 0 1 4 1 2
Case 1: 2.0000 Case 2: No such path.
给定n个圆,求从第一个圆到最后一个圆的最短路,要求路径全然包括在圆的覆盖下。
一開始以为圆与圆之间的处理必须经过圆心。无数的wa,苦苦找不到问题。一神牛提供了一组强大的数据,最终发现了问题。
把圆与圆相交全部交点找出来,排序,去重。然后枚举全部线段,找出线段与圆的全部交点,排序。去重,然后枚举每一段线段是否被某一个圆覆盖。假设不满足,直接
跳出,然后就是最短路的处理,连最短路也不会写了,直接堆了一个spfa,300+行代码,总算1Y了,泪目呀。。。。
代码:
- /* ***********************************************
- Author :rabbit
- Created Time :2014/7/3 22:46:38
- File Name :2.cpp
- ************************************************ */
- #pragma comment(linker, "/STACK:102400000,102400000")
- #include <stdio.h>
- #include <iostream>
- #include <algorithm>
- #include <sstream>
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
- #include <string>
- #include <time.h>
- #include <math.h>
- #include <queue>
- #include <stack>
- #include <set>
- #include <map>
- using namespace std;
- #define INF 0x3f3f3f3f
- #define eps 1e-6
- #define pi acos(-1.0)
- typedef long long ll;
- int dcmp(double x){
- if(fabs(x)<eps)return 0;
- return x>0?1:-1;
- }
- struct Point{
- double x,y;
- Point(double _x=0,double _y=0){
- x=_x;y=_y;
- }
- };
- Point operator + (Point a,Point b){
- return Point(a.x+b.x,a.y+b.y);
- }
- Point operator - (Point a, Point b){
- return Point(a.x-b.x,a.y-b.y);
- }
- Point operator * (Point a,double p){
- return Point(a.x*p,a.y*p);
- }
- Point operator / (Point a,double p){
- return Point(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 dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
- }
- double Dot(Point a, Point b){
- return a.x*b.x+a.y*b.y;
- }
- double Length(Point a){
- return sqrt(Dot(a,a));
- }
- double Angle(Point a,Point b){
- return acos(Dot(a,b)/Length(a)/Length(b));
- }
- double angle(Point a){
- return atan2(a.y,a.x);
- }
- double Cross(Point a,Point b){
- return a.x*b.y-a.y*b.x;
- }
- Point vecnit(Point x){
- return x/Length(x);
- }
- Point normal(Point x){
- return Point(-x.y,x.x)/Length(x);
- }
- Point Rotate(Point a,double rad){
- return Point(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
- }
- Point GetLineIntersection(Point p,Point v,Point q,Point w){
- Point u=p-q;
- double t=Cross(w,u)/Cross(v,w);
- return p+v*t;
- }
- struct Line{
- Point p,v;
- double ang;
- Line(){};
- Line(Point _p,Point _v):p(_p),v(_v){
- ang=atan2(v.y,v.x);
- }
- Point point(double a){
- return p+(v*a);
- }
- bool operator < (const Line &L)const{
- return ang<L.ang;
- }
- };
- Point GetLineIntersection(Line a,Line b){
- return GetLineIntersection(a.p,a.v,b.p,b.v);
- }
- bool OnLeft(const Line &L,const Point &p){
- return Cross(L.v,p-L.p)>=0;
- }
- vector<Point> HPI(vector<Line> L){
- int n=L.size();
- sort(L.begin(),L.end());
- int first,last;
- vector<Point> p(n);
- vector<Line> q(n);
- vector<Point> ans;
- q[last=first=0]=L[0];
- for(int i=1;i<n;i++){
- while(first<last&&!OnLeft(L[i],p[last-1]))last--;
- while(first<last&&!OnLeft(L[i],p[first]))first++;
- q[++last]=L[i];
- if(fabs(Cross(q[last].v,q[last-1].v))<eps){
- last--;
- if(OnLeft(q[last],L[i].p))q[last]=L[i];
- }
- if(first<last)p[last-1]=GetLineIntersection(q[last-1],q[last]);
- }
- while(first<last&&!OnLeft(q[first],p[last-1]))last--;
- if(last-first<=1)return ans;
- p[last]=GetLineIntersection(q[last],q[first]);
- for(int i=first;i<=last;i++)ans.push_back(p[i]);
- return ans;
- }
- double getarea(vector<Point> p){
- double ans=0;
- int n=p.size();
- for(int i=0;i<n;i++)
- ans+=Cross(p[i],p[(i+1)%n]);
- return fabs(ans)/2;
- }
- bool getdir(vector<Point> p){
- double ans=0;
- int n=p.size();
- for(int i=0;i<n;i++)
- ans+=Cross(p[i],p[(i+1)%n]);
- if(dcmp(ans)>0)return 1;
- return 0;
- }
- 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);
- }
- };
- bool OnSegment(Point p,Point a1,Point a2){
- return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<=0;
- }
- int getSegCircleIntersection(Line L, Circle C, Point* sol)
- {
- Point nor = normal(L.v);
- Line pl = Line(C.c, nor);
- Point ip = GetLineIntersection(pl, L);
- double dis = Length(ip - C.c);
- if (dcmp(dis - C.r) > 0) return 0;
- Point dxy = vecnit(L.v) * sqrt(C.r*C.r-dis*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 getCircleCircleIntersection(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=angle(c2.c-c1.c);
- double da=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
- Point p1=c1.point(a-da),p2=c1.point(a+da);
- sol.push_back(p1);
- if(p1==p2)return 1;
- sol.push_back(p2);
- return 2;
- }
- bool InCircle(Point x,Circle c){
- return dcmp(c.r-Length(c.c-x))>=0;
- }
- Point pp[50],p1[10010];
- double R[50],dist[1010][1010],dis[1010];
- int tot;
- int head[1010],tol,vis[1910];
- struct Edge{
- int next,to;
- double val;
- }edge[1001000];
- void addedge(int u,int v,double val){
- edge[tol].to=v;
- edge[tol].next=head[u];
- edge[tol].val=val;
- head[u]=tol++;
- }
- double spfa(int s,int t){
- memset(vis,0,sizeof(vis));queue<int> q;
- for(int i=0;i<tot;i++){
- if(i==s){
- vis[i]=1;
- dis[i]=0;
- q.push(i);
- }
- else dis[i]=INF;
- }
- while(!q.empty()){
- int u=q.front();
- q.pop();
- vis[u]=0;
- for(int i=head[u];i!=-1;i=edge[i].next){
- int v=edge[i].to;
- if(dis[v]>dis[u]+edge[i].val){
- dis[v]=dis[u]+edge[i].val;
- if(vis[v]==0){
- vis[v]=1;
- q.push(v);
- }
- }
- }
- }
- // cout<<"gg: "<<endl;
- //cout<<"tot="<<tot<<endl;
- // for(int i=0;i<tot;i++)cout<<dis[i]<<" ";cout<<endl;
- if(dis[t]<INF)return dis[t];
- return -1;
- }
- int main()
- {
- int T,n;
- // freopen("data.in","r",stdin);
- // freopen("data.out","w",stdout);
- scanf("%d",&T);
- for(int t=1;t<=T;t++){
- scanf("%d",&n);
- for(int i=0;i<n;i++)
- scanf("%lf%lf%lf",&pp[i].x,&pp[i].y,&R[i]);
- printf("Case %d: ",t);
- tot=0;
- for(int i=0;i<n;i++)p1[tot++]=pp[i];
- for(int i=0;i<n;i++)
- for(int j=i+1;j<n;j++){
- vector<Point> sol;
- int ret=getCircleCircleIntersection(Circle(pp[i],R[i]),Circle(pp[j],R[j]),sol);
- for(int k=0;k<ret;k++)
- p1[tot++]=sol[k];
- }
- sort(p1,p1+tot);
- tot=unique(p1,p1+tot)-p1;
- for(int i=0;i<1000;i++){
- dist[i][i]=0;
- for(int j=i+1;j<1000;j++)
- dist[i][j]=dist[j][i]=INF;
- }
- for(int i=0;i<tot;i++)
- for(int j=i+1;j<tot;j++){
- Point tt[100],sol[3];
- int hh=0;
- for(int k=0;k<n;k++){
- int ret=getSegCircleIntersection(Line(p1[i],p1[j]-p1[i]),Circle(pp[k],R[k]),sol);
- for(int d=0;d<ret;d++)
- tt[hh++]=sol[d];
- }
- tt[hh++]=p1[i];
- tt[hh++]=p1[j];
- sort(tt,tt+hh);
- hh=unique(tt,tt+hh)-tt;
- int ff=1;
- for(int d=0;d<hh-1;d++){
- int flag=0;
- for(int e=0;e<n;e++)
- if(InCircle(tt[d],Circle(pp[e],R[e]))&&InCircle(tt[d+1],Circle(pp[e],R[e]))){
- flag=1;break;
- }
- if(!flag){
- ff=0;break;
- }
- }
- if(ff)dist[i][j]=dist[j][i]=Length(p1[i]-p1[j]);
- }
- // cout<<"tot="<<tot<<endl;
- // for(int i=0;i<tot;i++)cout<<p1[i].x<<" "<<p1[i].y<<endl;
- // for(int i=0;i<tot;i++){
- // for(int j=0;j<tot;j++)cout<<dist[i][j]<<" ";
- // cout<<endl;
- // }
- int start,end;
- for(int i=0;i<tot;i++){
- if(p1[i]==pp[0])start=i;
- if(p1[i]==pp[n-1])end=i;
- }
- // cout<<"han "<<start<<" "<<end<<endl;
- memset(head,-1,sizeof(head));tol=0;
- for(int i=0;i<tot;i++)
- for(int j=i+1;j<tot;j++)
- if(dist[i][j]<INF){
- addedge(i,j,dist[i][j]);
- addedge(j,i,dist[i][j]);
- }
- // cout<<"tol="<<tol<<endl;
- double ans=spfa(start,end);
- if(ans==-1)puts("No such path.");
- else printf("%.4f\n",ans);
- }
- return 0;
- }
HDU 4063 线段与圆相交+最短路的更多相关文章
- hdu4063(圆与圆交+线段与圆交+最短路)
写几何题总是提心吊胆.精度问题真心吓人. 其实思路挺简单的一道题,真是什么算法和几何double搞到一块,心里就虚虚的. 思路:求出所有圆之间的交点,然后用这些交点跑一遍最短路就可以了. Aircra ...
- hdu 5120 (求两圆相交的面积
题意:告诉你两个圆环,求圆环相交的面积. /* gyt Live up to every day */ #include<cstdio> #include<cmath> #in ...
- luogu 1354 房间最短路问题 线段与直线相交 最短路
题目链接 题目描述 在一个长宽均为10,入口出口分别为(0,5).(10,5)的房间里,有几堵墙,每堵墙上有两个缺口,求入口到出口的最短路经. 输入输出格式 输入格式: 第一排为n(n<=20) ...
- HDU 4063 Aircraft --几何,最短路
题意: 给一些圆,要求从第一个圆的圆心走到最后一个圆的圆心,中间路径必须在某个圆内,求最短路径的长度. 解法: 易知要保持在圆内且路径最短,走两圆相交的点能使路径尽量短,所以我们找出所有的两圆相交的点 ...
- HDU 3264 Open-air shopping malls (计算几何-圆相交面积)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3264 题意:给你n个圆,坐标和半径,然后要在这n个圆的圆心画一个大圆,大圆与这n个圆相交的面积必须大于等 ...
- POJ_1556_The Doors_判断线段相交+最短路
POJ_1556_The Doors_判断线段相交+最短路 Description You are to find the length of the shortest path through a ...
- 【BZOJ 1033】 [ZJOI2008]杀蚂蚁antbuster(判断线段是否和圆相交)
[题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1033 [题意] https://www.zybuluo.com/Jerusalem/n ...
- HDU 1558 Segment set (并查集+线段非规范相交)
题目链接 题意 : 如果两个线段相交就属于同一集合,查询某条线段所属集合有多少线段,输出. 思路 : 先判断与其他线段是否相交,然后合并. #include <cstdio> #inclu ...
- HDU 3467 (求五个圆相交面积) Song of the Siren
还没开始写题解我就已经内牛满面了,从晚饭搞到现在,WA得我都快哭了呢 题意: 在DotA中,你现在1V5,但是你的英雄有一个半径为r的眩晕技能,已知敌方五个英雄的坐标,问能否将该技能投放到一个合适的位 ...
随机推荐
- IOS程式语法之block的使用掌握
在现阶IOBlock 是iOS在4.0之后新增的程式语法,严格来说block的概念并不算是基础程式设计的范围,对初学者来说也不是很容易了解,但是在iOS SDK 4.0之后,block几乎出现在所有新 ...
- layer和3D仿射变换
1.视图的显示基于图层,通过控制图层同样能控制显示效果,获取当前的视图的layer,并为其增加圆角边框. //设置layer边框的宽度为2 view.layer.borderWidth=; //如果需 ...
- GoLang中面向对象的三大特性
有过 JAVA 语言学习经历的朋友都知道,面向对象主要包括了三个基本特征:封装.继承和多态.封装,就是指运行的数据和函数绑定在一起,JAVA 中主要是通过 super 指针来完成的:继承,就是指 cl ...
- MongoDB学习笔记(一)--基础
Insert MongoD ...
- web中的水晶报表 "出现通信错误。将停止打印"
被这个问题快折腾死,死活都找不到原因,找了一堆解答,无外乎这几种情况,但都不管用 在Page_Init中绑定数据.无效. activex控件的版本,我试过10.2.0.1146等多个版本的dll,10 ...
- 使用AKKA做分布式爬虫的思路
上周公司其它小组在讨论做分布式爬虫,我也思考了一下.提了一个方案,就是使用akka分布式rpc框架来做,自己写master和worker程序,client向master提交begin任务或者其它爬虫需 ...
- Roo中的@Version
首页 关于 Roo中的@Version 发表回复 问题提出 当我们为entity添加@RooJpaActiveRecord注解时,Roo为我们自动生成了一个名为Entity_Roo_Jpa_Entit ...
- Jsp之神笔记
JSP笔记 Tomcatserver port: port就是指的某一个程序网络入口,Tomcat的初始化port为:8080: port的个数:256*256=65536个: 一般常见协议的缺省po ...
- Cocos2d-x新建模板编译问题总汇
0:关于使用VC模板创建模板时候脚本错误.改动..\cocos2d-x-2.2.2\template\msvc\CCAppWiz.win32\HTML\1033中文件属性中:安全->解除锁定. ...
- 在命令行上 Ubuntu 下使用 mutt 和 msmtp 发送 Gmail 邮件
在命令行写email from ubuntu 参考: http://www.habadog.com/2011/11/23/send-mail-with-msmtp-mutt-linux ...