[模拟退火 二分答案] BZOJ 1038 [ZJOI2008]瞭望塔

来源:互联网 发布:dbscan聚类算法原理 编辑:程序博客网 时间:2024/05/20 18:17


正解半平面交,%%% PoPoQQQ : http://blog.csdn.net/popoqqq/article/details/39340759

"确定瞭望塔的高度的时候我们选择二分处理 对于二分的每一个值 我们把折线上的端点从左到右枚举 瞭望塔的塔尖到每个端点的连线必须从左到右逆时针顺序 否则就会被遮挡"

#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>#include<ctime>#define eps 1e-4using namespace std;inline char nc(){static char buf[100000],*p1=buf,*p2=buf;if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }return *p1++;}inline void read(int &x){char c=nc(),b=1;for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}inline int dcmp(double a,double b){if (fabs(a-b)<1e-5) return 0;if (a<b) return -1;return 1;}struct Point{double x,y;Point(double x=0,double y=0):x(x),y(y) { }friend double Cross(Point p1,Point p2,Point p0){return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}}P[305];int n;double x1,xn;double ans=1e130;inline double rnd(){return (rand()%1000)/1000.0;}inline double calc(double x){for (int i=1;i<n;i++)if (dcmp(P[i].x,x)<=0 && dcmp(x,P[i+1].x)<=0)return P[i].y+(P[i+1].y-P[i].y)/(P[i+1].x-P[i].x)*(x-P[i].x);}Point Q[305];int r;inline int C(Point E){r=0;for (int i=1;i<=n;i++){while (r && dcmp(Cross(P[i],Q[r],E),0)>=0) r--;Q[++r]=P[i];}return r;}inline bool Check(Point E){for(int i=2;i<=n;i++)  if(dcmp(Cross(P[i-1],P[i],E),0)<0)  return 0;  return 1;} inline double Bin(double x){double L=0,R=1e11,MID;double y=calc(x);while (R-L>1e-5)if (Check(Point(x,y+(MID=(L+R)/2))))R=MID;elseL=MID;ans=min(ans,(L+R)/2);return (L+R)/2;}inline void SA(){#define beta .99#define EPS 1e-5 double nx,sx,now,delta,ret;sx=(x1+xn)/2;now=Bin(sx);for (double T=xn-x1;T>EPS;T*=beta){nx=sx+T*(rnd()*2-1);if(nx<x1 || nx>xn) continue;   ret=Bin(nx);delta=now-ret;if (delta>0 || rnd()<exp(delta/T))sx=nx,now=ret;}}int main(){#define Case 2srand(10086);  int ix;freopen("t.in","r",stdin);freopen("t.out","w",stdout);read(n);for (int i=1;i<=n;i++) read(ix),P[i].x=ix;for (int i=1;i<=n;i++) read(ix),P[i].y=ix;x1=P[1].x; xn=P[n].x;for (int i=1;i<=Case;i++)SA();printf("%.3lf\n",ans);return 0;}


0 0