首页 > 代码库 > BZOJ 3007 解救小云公主 二分答案+对偶图
BZOJ 3007 解救小云公主 二分答案+对偶图
题目大意:给定一个矩形和矩形内的一些点。求一条左下角到右上角的路径。使全部点到这条路径的最小距离最大
最小距离最大。果断二分答案
如今问题转化成了给定矩形中的一些圆形障碍物求左下角和右上角是否连通
然后就是对偶图的问题了
左下角和右上角连通等价于对偶图中左上两条边和右下两条边不连通
因此将全部相交的圆之间连边,从左上两条边广搜就可以
时间复杂度O(n^2log(min(r,l)/EPS))
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 3030 #define S 0 #define T (n+1) using namespace std; struct Point{ double x,y; friend istream& operator >> (istream &_,Point &p) { scanf("%lf%lf",&p.x,&p.y); return _; } friend double Distance(const Point &p1,const Point &p2) { return sqrt( (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y) ); } }pos,points[M]; struct abcd{ int to,next; }table[M*M]; int head[M],tot; int n; double dis[M][M]; void Initialize() { memset(head,0,sizeof head); tot=0; } void Add(int x,int y) { table[++tot].to=y; table[tot].next=head[x]; head[x]=tot; } bool BFS() { static int q[M]; static bool v[M]; int i,r=0,h=0; memset(v,0,sizeof v); v[S]=true;q[++r]=S; while(r!=h) { int x=q[++h]; for(i=head[x];i;i=table[i].next) if(!v[table[i].to]) { v[table[i].to]=true; q[++r]=table[i].to; if(table[i].to==T) return true; } } return false; } bool Judge(double r) { int i,j; Initialize(); for(i=1;i<=n;i++) { if( points[i].x-1<r || pos.y-points[i].y<r ) Add(S,i); if( points[i].y-1<r || pos.x-points[i].x<r ) Add(i,T); } for(i=1;i<=n;i++) for(j=1;j<i;j++) if( dis[i][j]<2*r ) Add(i,j),Add(j,i); return !BFS(); } double Bisection() { double l=0,r=min(pos.x-1,pos.y-1); while(r-l>1e-4) { double mid=(l+r)/2.0; if( Judge(mid) ) l=mid; else r=mid; } return (l+r)/2.0; } int main() { int i,j; cin>>n>>pos; for(i=1;i<=n;i++) cin>>points[i]; for(i=1;i<=n;i++) for(j=1;j<i;j++) dis[i][j]=Distance(points[i],points[j]); printf("%.2lf\n", Bisection() ); }
BZOJ 3007 解救小云公主 二分答案+对偶图
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。