[bzoj1038] [ZJOI2008]瞭望塔
看到半平面交吓傻了。
Po姐教你模拟退火乱搞233
模拟退火横坐标,然后塔的高度二分一下就行了。
然而交上去一直tle= =。。。。把模拟退火那部分改得和标程一模一样还是跪。。
最后真相是二分的时候double精度会炸(掀桌。。。然而标程不知为啥用double活得好好的(虽然随便随机一个数据就能卡。。
改成long double就过了= =
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 #define d double 7 #define ld long double 8 using namespace std; 9 const int maxn=323; 10 const d eps=1e-7; 11 struct poi{ 12 int x,y; 13 }a[maxn]; 14 d ansx,ansaddy,nowx,nowy;int posl,posr; 15 int i,j,k,n,m; 16 17 int ra,fh;char rx; 18 inline int read(){ 19 rx=getchar(),ra=0,fh=1; 20 while((rx<'0'||rx>'9')&&rx!='-')rx=getchar(); 21 if(rx=='-')fh=-1,rx=getchar(); 22 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh; 23 } 24 25 inline d randlf(){ 26 return rand()%10000/10000.0; 27 } 28 bool judge(){ 29 int i; 30 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)) 31 return 0; 32 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)) 33 return 0; 34 return 1; 35 } 36 inline d geth(){ 37 int L=1,R=n,MID;ld sy,l,r,mid; 38 while(L<R) 39 if(a[(MID=(L+R+1)>>1)].x<=nowx)L=MID;else R=MID-1; 40 posl=L,posr=L+1; 41 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); 42 l=0,r=1e11;//printf("geth: x:%.8lf l r:%d %d sy:%.3lf\n",nowx,a[posl].x,a[posr].x,sy); 43 while(l+1e-7<r){ 44 mid=(l+r)/2;nowy=sy+mid; 45 if(judge())r=mid;//,printf("success: %.2lf %.2lf %.9lf\n",nowx,(d)sy,(d)mid); 46 else l=mid;//,printf("failed: %.2lf %.2lf %.9lf %.9lf %.9lf\n",nowx,(d)sy,(d)mid,(d)l,(d)r); 47 } 48 if(l<ansaddy)ansaddy=l,ansx=nowx; 49 return l; 50 }//<n*64 51 inline void SA(){ 52 d T=a[n].x-a[1].x,prex,tmpaddy,nowaddy; 53 nowx=ansx=(a[n].x+a[1].x)/2.0;nowaddy=geth();//printf(" %.2lf\n",nowx); 54 while(T>1e-5){ 55 T*=0.99;//printf("! %d\n",fabs(nowaddy-geth())<=eps); 56 prex=nowx,nowx+=T*(randlf()*2-1); 57 // printf("try:%.3lf\n",nowx); 58 if(nowx<a[1].x||nowx>a[n].x){nowx=prex;T/=0.991;continue;} 59 tmpaddy=geth(); 60 61 if(tmpaddy>nowaddy&&exp((nowaddy-tmpaddy)/T)<randlf()) 62 nowx=prex; 63 else nowaddy=tmpaddy; 64 } 65 for(int i=1;i<=1023;i++){ 66 nowx=ansx+T*(randlf()*2-1);//printf("try1:%.3lf\n",nowx); 67 if(nowx<a[1].x||nowx>a[n].x)continue; 68 geth(); 69 } 70 } 71 int main(){ 72 n=read();srand(233); 73 // srand(19980406); 74 for(i=1;i<=n;i++)a[i].x=read(); 75 for(i=1;i<=n;i++)a[i].y=read();ansaddy=1e11; 76 SA(); 77 printf("%.3lf\n",ansaddy+eps);//printf("ansx: %.3lf\n",ansx); 78 return 0; 79 }