您的位置:首页 > 其它

[bzoj1038] [ZJOI2008]瞭望塔

2016-03-21 13:01 309 查看
  看到半平面交吓傻了。

  Po姐教你模拟退火乱搞233

  模拟退火横坐标,然后塔的高度二分一下就行了。

  然而交上去一直tle= =。。。。把模拟退火那部分改得和标程一模一样还是跪。。

  最后真相是二分的时候double精度会炸(掀桌。。。然而标程不知为啥用double活得好好的(虽然随便随机一个数据就能卡。。

  改成long double就过了= =

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdlib>
#define d double
#define ld long double
using namespace std;
const int maxn=323;
const d eps=1e-7;
struct poi{
int x,y;
}a[maxn];
d ansx,ansaddy,nowx,nowy;int posl,posr;
int i,j,k,n,m;

int ra,fh;char rx;
inline int read(){
rx=getchar(),ra=0,fh=1;
while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
if(rx=='-')fh=-1,rx=getchar();
while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
}

inline d randlf(){
return rand()%10000/10000.0;
}
bool judge(){
int i;
for(i=1;i<posl;i++)if((nowy-a[i].y)*(nowx-a[i+1].x)>(nowy-a[i+1].y)*(nowx-a[i].x))
return 0;
for(i=posr;i<n;i++)if((a[i].y-nowy)*(a[i+1].x-nowx)>(a[i+1].y-nowy)*(a[i].x-nowx))
return 0;
return 1;
}
inline d geth(){
int L=1,R=n,MID;ld sy,l,r,mid;
while(L<R)
if(a[(MID=(L+R+1)>>1)].x<=nowx)L=MID;else R=MID-1;
posl=L,posr=L+1;
if(a[L].x==nowx)posl--,sy=a[L].y;else sy=a[posl].y+(a[posr].y-a[posl].y)*(nowx-a[posl].x)/(a[posr].x-a[posl].x);
l=0,r=1e11;//printf("geth:  x:%.8lf   l r:%d %d   sy:%.3lf\n",nowx,a[posl].x,a[posr].x,sy);
while(l+1e-7<r){
mid=(l+r)/2;nowy=sy+mid;
if(judge())r=mid;//,printf("success:  %.2lf %.2lf   %.9lf\n",nowx,(d)sy,(d)mid);
else l=mid;//,printf("failed:  %.2lf %.2lf   %.9lf  %.9lf %.9lf\n",nowx,(d)sy,(d)mid,(d)l,(d)r);
}
if(l<ansaddy)ansaddy=l,ansx=nowx;
return l;
}//<n*64
inline void SA(){
d T=a
.x-a[1].x,prex,tmpaddy,nowaddy;
nowx=ansx=(a
.x+a[1].x)/2.0;nowaddy=geth();//printf("   %.2lf\n",nowx);
while(T>1e-5){
T*=0.99;//printf("!  %d\n",fabs(nowaddy-geth())<=eps);
prex=nowx,nowx+=T*(randlf()*2-1);
//    printf("try:%.3lf\n",nowx);
if(nowx<a[1].x||nowx>a
.x){nowx=prex;T/=0.991;continue;}
tmpaddy=geth();

if(tmpaddy>nowaddy&&exp((nowaddy-tmpaddy)/T)<randlf())
nowx=prex;
else nowaddy=tmpaddy;
}
for(int i=1;i<=1023;i++){
nowx=ansx+T*(randlf()*2-1);//printf("try1:%.3lf\n",nowx);
if(nowx<a[1].x||nowx>a
.x)continue;
geth();
}
}
int main(){
n=read();srand(233);
//    srand(19980406);
for(i=1;i<=n;i++)a[i].x=read();
for(i=1;i<=n;i++)a[i].y=read();ansaddy=1e11;
SA();
printf("%.3lf\n",ansaddy+eps);//printf("ansx:  %.3lf\n",ansx);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: