BZOJ1038: [ZJOI2008]瞭望塔
2017-02-01 21:48
267 查看
传送门
半平面交..
好蛋疼的一道题,调了一下午。
思路很简单,搞出半平面交后计算每个点到另一边的距离,取min即可。
但是有很多小细节,比方$\infty$要开大点。还有就是判定$Onleft$的时候在线上也要判定。
半平面交..
好蛋疼的一道题,调了一下午。
思路很简单,搞出半平面交后计算每个点到另一边的距离,取min即可。
但是有很多小细节,比方$\infty$要开大点。还有就是判定$Onleft$的时候在线上也要判定。
//BZOJ1038 //by Cydiater //2017.2.1 #include <iostream> #include <map> #include <ctime> #include <cmath> #include <queue> #include <cstdlib> #include <cstdio> #include <iomanip> #include <cstring> #include <string> #include <algorithm> #include <bitset> #include <set> #include <vector> using namespace std; #define ll long long #define up(i,j,n) for(int i=j;i<=n;i++) #define down(i,j,n) for(int i=j;i>=n;i--) #define cmax(a,b) a=max(a,b) #define cmin(a,b) a=min(a,b) #define db double #define Vector Point const int MAXN=1e3+5; const db oo=1e15; const db eps=1e-10; inline int read(){ char ch=getchar();int x=0,f=1; while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int dcmp(db x){if(fabs(x)<eps)return 0;else return x<0?-1:1;} struct Point{ db x,y; Point(db x=0,db y=0):x(x),y(y){} }; Vector operator + (Point x,Point y){return Vector(x.x+y.x,x.y+y.y);} Vector operator - (Point x,Point y){return Vector(x.x-y.x,x.y-y.y);} Vector operator * (Vector x,db p){return Vector(x.x*p,x.y*p);} Vector operator / (Vector x,db p){return Vector(x.x/p,x.y/p);} bool operator < (const Vector &x,const Vector &y){return dcmp(x.x-y.x)==0?x.y<y.y:x.x<y.x;} struct Line{ Point P;Vector v;db ang; Line(){} Line(Point P,Vector v):P(P),v(v){ang=atan2(v.y,v.x);} }; bool operator < (const Line &x,const Line &y){return x.ang<y.ang;} int N,head,tail,top1,top2,pos; Point P[MAXN],ch1[MAXN],ch2[MAXN]; db ans=oo; Line L[MAXN],q[MAXN],lh1[MAXN],lh2[MAXN]; namespace solution{ db Cross(Vector x,Vector y){return x.x*y.y-x.y*y.x;} bool Onleft(Point p,Line l){return dcmp(Cross(p-l.P,l.v))<=0;} db Dot(Vector x,Vector y){return x.x*y.x+x.y*y.y;} db Len(Vector x){return sqrt(Dot(x,x));} Point LineMeet(Line x,Line y){ db t=Cross(y.v,x.P-y.P)/Cross(x.v,y.v); return x.P+x.v*t; } void Prepare(){ N=read(); up(i,1,N)P[i].x=read(); up(i,1,N)P[i].y=read(); memcpy(ch1,P,sizeof(ch1)); top1=N; up(i,1,N-1)L[i]=Line(P[i],P[i+1]-P[i]); memcpy(lh1,L,sizeof(lh1)); } db walk1(db x){ db y=-oo; up(i,1,top2)if(dcmp(lh2[i].v.x)!=0){ db k=lh2[i].v.y/lh2[i].v.x; db b=lh2[i].P.y-k*lh2[i].P.x; cmax(y,k*x+b); } return y; } db walk2(db x){ if(x>ch1[top1-1].x)return -oo; down(i,top1-1,1)if(lh1[i].P.x<=x){ db k=lh1[i].v.y/lh1[i].v.x; db b=lh1[i].P.y-k*lh1[i].P.x; return k*x+b; } return -oo; } void Solve(){ sort(L+1,L+N); head=1;tail=0;q[++tail]=L[1]; up(i,2,N-1){ while(head<tail&&!Onleft(P[tail-1],L[i]))tail--; while(head<tail&&!Onleft(P[head],L[i]))head++; q[++tail]=L[i]; if(dcmp(q[tail].ang-q[tail-1].ang)==0){ tail--; if(Onleft(L[i].P,q[tail]))q[tail]=L[i]; } if(head<tail)P[tail-1]=LineMeet(q[tail-1],q[tail]); } while(head<tail&&!Onleft(P[tail-1],q[head]))tail--; top2=tail-head+1; up(i,head,tail){ ch2[i-head+1]=P[i]; lh2[i-head+1]=q[i]; } /*up(i,1,top1-1){ printf("%lf %lf\n",ch1[i].x,ch1[i].y); }*/ up(i,1,top1)cmin(ans,walk1(ch1[i].x)-ch1[i].y); up(i,1,top2-1)cmin(ans,ch2[i].y-walk2(ch2[i].x)); if(dcmp(ans-oo)==0)ans=0; printf("%.3lf\n",dcmp(ans)==0?0:ans); } } int main(){ //freopen("input.in","r",stdin); //freopen("out1.out","w",stdout); using namespace solution; Prepare(); Solve(); return 0; }
相关文章推荐
- BZOJ1038 [ZJOI2008]瞭望塔
- bzoj1038 [ZJOI2008]瞭望塔
- 【半平面交】【计算几何】[BZOJ1038][ZJOI2008]瞭望塔
- BZOJ 1038 ZJOI2008 瞭望塔 半平面交
- BZOJ 1038: [ZJOI2008]瞭望塔 半平面交
- 【BZOJ】1038: [ZJOI2008]瞭望塔
- 【BZOJ1038】【ZJOI2008】瞭望塔 [模拟退火]
- 【BZOJ 1038】 [ZJOI2008]瞭望塔
- [BZOJ 1038][ZJOI 2008]瞭望塔(半平面交)
- 【bzoj1038】【ZJOI2008】【瞭望塔】【半平面交】
- [BZOJ1038][洛谷P2600]-[ZJOI2008]瞭望塔-半平面交
- bzoj1038: [ZJOI2008]瞭望塔
- BZOJ 1038 ZJOI 2008 瞭望塔 半平面交
- 【ZJOI2008】【BZOJ1038】瞭望塔
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- [半平面交] BZOJ1038: [ZJOI2008]瞭望塔
- BZOJ 1038 ZJOI2008 瞭望塔 模拟退火+二分答案
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- [模拟退火 二分答案] BZOJ 1038 [ZJOI2008]瞭望塔
- bzoj1038 [ZJOI2008]瞭望塔 枚举