zoj2318 getout(计算几何)

xiaoxiao2021-02-28  136

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1318

题意:

你是一个圆,二维坐标中有很多其他n个圆,给出n个圆心及半径,再给你自己的圆心及半径,问这个圆能不能逃出这n个圆的包围。

tip:

好神奇的题。。首先考虑把自己这个圆变成点,把别的圆的半径加上自己这个半径就好了。如果某两个圆相交或相切,那么他们组成的封闭区间可以用连接其两圆心的线段表示,这样能得到若干线段,于是问题变成,若干线段中,是否能组成一个封闭区域,且起始圆心在其内。 按顺时针扫描每一条边,如果点在里面,点与所有线段两个端点角度和为2π,如果逆时针来,就是-2π。 如果在多边形外的话,和必然是0,于是加边i j 边权为从起始圆心到I和到j的角度和(正负各加一条),如果整个图有负环,就相当于找到一个-2π,说明出不去了,spfa即可。。

#include <cstdio> #include <iostream> #include <cstring> #include <queue> #include <cmath> #include <algorithm> using namespace std; const int maxn = 340; const double eps = 1e-8; int n,tot,head[maxn],num[maxn]; bool inq[maxn]; struct Tcircle{ double x,y,r; }p[maxn]; double dis[maxn]; struct node{ int u,v,next; double w; }edges[maxn*maxn]; void add(int u,int v,double w){ edges[tot].v = v;edges[tot].w = w;edges[tot].next = head[u];head[u] = tot++; } void init(){ tot = 0;memset(head,-1,sizeof(head)); scanf("%d",&n); for(int i = 1 ;i <= n ; i++){ scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].r); } scanf("%lf%lf%lf",&p[0].x,&p[0].y,&p[0].r); for(int i = 1; i <= n ; i++) p[i].r += p[0].r; } double dist(int i,int j){ return sqrt( (p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y) ); } bool spfa(){ queue<int>q; for(int i = 1;i <= n;i++){ q.push(i); inq[i] = true; num[i] = 0; dis[i] = 0.0; } while(!q.empty()){ int tmp = q.front();q.pop(); inq[tmp] = 0; for(int k = head[tmp];k != -1;k = edges[k].next){ if(dis[edges[k].v] > eps+dis[tmp]+edges[k].w){ dis[edges[k].v] = dis[tmp]+edges[k].w; if(!inq[edges[k].v]){ inq[edges[k].v] = true; q.push(edges[k].v); num[edges[k].v]++; if(num[edges[k].v] > n-1) return true; } } } } return false; } void sov(){ for(int i = 1; i <= n ; i++){ for(int j = i+1 ; j <= n ; j++){ if(p[i].r+p[j].r-dist(i,j) <= eps) continue; double ang = ( (p[i].x-p[0].x)*(p[j].x-p[0].x) + (p[i].y-p[0].y)*(p[j].y-p[0].y) )/dist(0,i)/dist(0,j); ang = acos(ang); if( (p[i].x-p[0].x) *(p[j].y-p[0].y) - (p[j].x-p[0].x) * (p[i].y-p[0].y) >= 0){ add(i,j,ang);add(j,i,-ang); } else{ add(i,j,-ang);add(j,i,ang); } } } } int main(){ int T; scanf("%d",&T); while(T--){ init(); sov(); if(spfa()) printf("NO\n"); else printf("YES\n"); if(T) printf("\n"); } }
转载请注明原文地址: https://www.6miu.com/read-19872.html

最新回复(0)