标签:des style blog java color strong
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 线段与圆相交+最短路,布布扣,bubuko.com
标签:des style blog java color strong
原文地址:http://blog.csdn.net/xianxingwuguan1/article/details/37045007