【BZOJ】【1020】【SHOI2008】安全的航线flight
2015-04-12 18:14
330 查看
计算几何/二分/迭代/搜索+剪枝
写三个tag可能是因为从哪个方向来理解都可以吧……我完全不会计算几何所以抄了ydc的代码
题解:http://ydcydcy1.blog.163.com/blog/static/21608904020131492229367/
那篇莫涛的论文:http://pan.baidu.com/s/1bn6IxJp
大概流程如下:
1.初始化孤地点可能位于的线段集合为整条航线。
2.对于长$L$的某条线段,左端点与陆地的最近点为$P_1$,右端点与陆地的最近点为$P_2$,那么该线段上的孤地距离将受$P_1$与$P_2$影响。具体来说,利用二分求出改线段上的点$P$使得$$ Minimize \ y = max\{Dis\{P,P_1\},Dis\{P,P_2\}\}$$若$y$小于已有的最优答案,那么可以删除该线段。
3.取所有线段的中点更新答案。
4.将所有线段从重点分成左右两条线段。
5.不断进行2,3,4直到线段的集合为空。
整个过程中最复杂的计算集合操作是第3步中求点与线段的距离,并且不会出现因精度导致的判断问题,而运行速度也不错,极限数举只需0.05秒,是一个相当优秀的算法。
(才怪啊!那判断点是否在陆地上不是也得写射线法和点在线段上?判断是否在多边形内部……)
/************************************************************** Problem: 1020 User: Tunix Language: C++ Result: Accepted Time:92 ms Memory:32544 kb ****************************************************************/ //BZOJ 1020 #include<cmath> #include<vector> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define rep(i,n) for(int i=0;i<n;++i) #define F(i,j,n) for(int i=j;i<=n;++i) #define D(i,j,n) for(int i=j;i>=n;--i) #define pb push_back using namespace std; inline int getint(){ int v=0,sign=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} return v*sign; } const int N=30,M=40,MAXQ=1e6,INF=~0u>>2; const double eps=1e-16; typedef long long LL; typedef double db; /******************tamplate*********************/ int dcmp(db p){if(fabs(p)<eps) return 0;else return p>eps?1:-1;} int n,m; db ans; struct Point{ db x,y; Point(){} Point(db x,db y):x(x),y(y){} void Read(){scanf("%lf %lf",&x,&y);} }temp ; Point operator + (const Point &a,const Point &b){return Point(a.x+b.x,a.y+b.y);} Point operator - (const Point &a,const Point &b){return Point(a.x-b.x,a.y-b.y);} Point operator * (const Point &a,db p){return Point(a.x*p,a.y*p);} Point operator / (const Point &a,db p){return Point(a.x/p,a.y/p);} bool operator == (const Point &a,const Point &b){return !dcmp(a.x-b.x)&&!dcmp(a.y-b.y);} typedef Point Vector; double Dot(const Vector &a,const Vector &b){return a.x*b.x+a.y*b.y;} double Len(const Vector &a){return sqrt(Dot(a,a));} double Cross(const Vector &a,const Vector &b){return a.x*b.y-a.y*b.x;} Vector Normal(const Vector &a){return Vector(-a.y,a.x);} bool On(const Point &a,const Point &b,const Point &c){ return !dcmp(Cross(b-a,c-a))&& dcmp((a.x-b.x)*(a.x-c.x))<=0&&dcmp((a.y-b.y)*(a.y-c.y))<=0; } bool inter(const Point &a,const Point &b,const Point &c,const Point &d){ return dcmp(Cross(c-a,b-a)*Cross(d-a,b-a))<=0 && dcmp(Cross(a-c,d-c)*Cross(b-c,d-c))<=0; } Point getinter(const Point &a,const Vector &b,const Point &c,const Vector &d){ Vector u=a-c; double t=Cross(d,u)/Cross(b,d); return a+b*t; } struct Seg{ Point a,b; Seg(){} Seg(const Point &a,const Point &b):a(a),b(b){} }queue[MAXQ]; struct Polygon{ Point p[M]; int tot; bool In(Point &point){ int total=0; F(i,1,tot) if (On(point,p[i],p[i%tot+1])) return true; Point Ray=Point(-10001,point.y+0.1); point.y+=0.1; F(i,1,tot) total=total+inter(Ray,point,p[i],p[i%tot+1]); point.y-=0.1; return total&1; } }island ; struct near{ Point P; double dis; near(){} near(const Point &a,double b):P(a),dis(b){} }; near DISPS(const Point &a,const Point &b,const Point &c){ if (b==c) return near(b,Len(b-a)); Vector v1=c-b,v2=a-b,v3=a-c; if (dcmp(Dot(v1,v2))<=0) return near(b,Len(v2)); if (dcmp(Dot(v1,v3))>=0) return near(c,Len(v3)); Vector v=Normal(b-c); Point ans=getinter(a,v,b,v1); return near(ans,Len(a-ans)); } bool check(Point &P){ F(i,1,n) if (island[i].In(P)) return true; return false; } near Find(Point &P){ if (check(P)) return near(P,0); near ans1; ans1.dis=1<<30; F(i,1,n) F(j,1,island[i].tot){ near get=DISPS(P,island[i].p[j],island[i].p[j%island[i].tot+1]); if (dcmp(ans1.dis-get.dis)>=0) ans1=get; } ans=max(ans,ans1.dis); return ans1; } void read(){ n=getint(); m=getint(); F(i,1,m) temp[i].Read(); F(i,1,n){ island[i].tot=getint(); F(j,1,island[i].tot) island[i].p[j].Read(); } } void search(){ int front=0,rear=0; F(i,1,m-1) queue[++rear]=Seg(temp[i],temp[i+1]),Find(temp[i]); Find(temp[m]); Seg head; while(front!=rear){ head=queue[front=front%MAXQ+1]; Point p1=Find(head.a).P,p2=Find(head.b).P, l=head.a,r=head.b,mid=(l+r)/2; while(Len(r-l)>1e-4){ Point mid=(r+l)/2; if (Len(mid-p1)<Len(mid-p2)) l=mid; else r=mid; } double nowans=max(Len(l-p1),Len(l-p2)); Find(l); if (ans+0.005<nowans) queue[rear=rear%MAXQ+1]=Seg(head.a,mid), queue[rear=rear%MAXQ+1]=Seg(mid,head.b); } } int main(){ #ifndef ONLINE_JUDGE freopen("1020.in","r",stdin); freopen("1020.out","w",stdout); #endif read(); search(); printf("%.2lf\n",ans); return 0; }
View Code
1020: [SHOI2008]安全的航线flight
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 786 Solved: 254
[Submit][Status][Discuss]
Description
在设计航线的时候,安全是一个很重要的问题。首先,最重要的是应采取一切措施确保飞行不会发生任何事故,但同时也需要做好最坏的打算,一旦事故发生,就要确
保乘客有尽量高的生还几率。当飞机迫降到海上的时候,最近的陆地就是一个关键的因素。航线中最危险的地方就是距离最近的陆地最远的地方,我们称这种点为这
条航线“孤地点”。孤地点到最近陆地的距离被称为“孤地距离”。作为航空公司的高级顾问,你接受的第一个任务就是尽量找出一条航线的孤地点,并计算这条航
线的孤地距离。为了简化问题,我们认为地图是一个二维平面,陆地可以用多边形近似,飞行线路为一条折线。航线的起点和终点都在陆地上,但中间的转折点是可
能在海上(如下图所示,方格标示出了孤地点)。
Input
输入的第一行包括两个整数C和N(1≤C≤20,2≤N≤20),分别代表陆地的数目的航线的转折点的数目。接下来有N行,每行有两个整数x,y。
(x,y)表示一个航线转折点的坐标,第一个转折点为航线的起点,最后一个转折点为航线的终点。接下来的输入将用来描述C块大陆。每块输入由一个正整数M
开始(M≤30),M表示多边形的顶点个数,接下来的M行,每行会包含两个整数x,y,(x,y)表示多边形的一个顶点坐标,我们保证这些顶点以顺时针或
逆时针给出了该多边形的闭包,不会出现某些边相交的情况。此外我们也保证输入数据中任何两块大陆不会相交。输入的所有坐标将保证在-10000到
10000的范围之间。
Output
输出一个浮点数,表示航线的孤地距离,数据保留2位小数。Sample Input
1 2-9 -6
5 1
3
0 16
-16 -12
17 -6
Sample Output
0.00HINT
Source
NWERC 2007[Submit][Status][Discuss]
相关文章推荐
- BZOJ 1020 [SHOI2008]安全的航线flight
- 1020: [SHOI2008]安全的航线flight - BZOJ
- [bzoj1020][SHOI2008]安全的航线flight【迭代】【计算几何】
- 【BZOJ 1020】 [SHOI2008]安全的航线flight
- BZOJ 1020——[SHOI2008]安全的航线flight
- 【BZOJ 1020】 [SHOI2008]安全的航线flight
- BZOJ_1020_[SHOI2008]_安全的航线flight_(计算几何+二分)
- [计算几何][SHOI2008]安全的航线flight
- bzoj1020 安全的航线flight
- BZOJ 1020 安全的航线flight
- [BZOJ]1020安全的航线
- bzoj 1020 安全的航线|计算几何
- bzoj1023 [SHOI2008]cactus仙人掌图
- 【线段树】bzoj1018 [SHOI2008]堵塞的交通traffic
- bzoj 1019: [SHOI2008]汉诺塔(打表)
- [Anti-Nim Anti-SG SJ定理] BZOJ 1022 [SHOI2008]小约翰的游戏John
- [bzoj1018][SHOI2008]堵塞的交通traffic——线段树
- [BZOJ1018][SHOI2008]堵塞的交通traffic 线段树维护连通性
- BZOJ1018: [SHOI2008]堵塞的交通traffic
- [BZOJ1018][SHOI2008]堵塞的交通traffic(线段树)