HDU2438 三分枚举角度

xiaoxiao2021-02-27  151

 要使汽车能转过此弯道,那么就是汽车的左边尽量贴着那个直角点,而汽车的右下后方的点尽量贴着最下面的边。 我们以O点为原点建立直角坐标系,我们可以根据角a给出P点横坐标的函数F(a)   那么很容易得到:   其中有条件:,可以很容易证明是一个单峰函数,所以接下来就是三分了,如果的最大值小于等于   y,那么就能通过此直角弯道,否则就通不过。 代码如下: #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #define pi 3.1415 using namespace std; const double eps = 1e-4; double l,x,y,w; double calu(double a){ return l*cos(a)+(w-x*cos(a))/sin(a); } double ternary_search(double l,double r){ double ll,rr; while(r-l>eps){ ll=(2*l+r)/3; rr=(2*r+l)/3; if(calu(ll)>calu(rr)) r=rr; else l=ll; } return r; } int main() { while(cin>>x>>y>>l>>w){ double l=0,r=pi/2; double tmp=ternary_search(l,r); if(calu(tmp)<=y) puts("yes"); else puts("no"); } return 0; } 题目大意:给你一个拐角,两边的路的宽度分别为x,y。汽车的长和宽分别为h,w。问你这个汽车否转弯成功。 解题思路:如图,枚举角度。 这是一个凸函数所以三分枚举角度。

Turn the corner

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2009    Accepted Submission(s): 765 Problem Description Mr. West bought a new car! So he is travelling around the city. One day he comes to a vertical corner. The street he is currently in has a width x, the street he wants to turn to has a width y. The car has a length l and a width d. Can Mr. West go across the corner?   Input Every line has four real numbers, x, y, l and w. Proceed to the end of file.   Output If he can go across the corner, print "yes". Print "no" otherwise.   Sample Input 10 6 13.5 4 10 6 14.5 4   Sample Output yes no   Source 2008 Asia Harbin Regional Contest Online   [cpp] view plain copy print ? #include <iostream>  #include<time.h>  #include<stdio.h>  #include<string.h>  #include<stdlib.h>  #include<string>  #include<cmath>  #include<map>    #define eps 1e-10  #define PI acos(-1)    using namespace std;    const int maxn = 220;    #define LL long long      double x, y, l, w;      double Del(double ang)  {      double s = l*cos(ang)+w*sin(ang)-x;      double h = s*tan(ang)+w*cos(ang);      return h;  }      int main()  {      while(cin >>x>>y>>l>>w)      {            double Max = 0.0;          double left = 0;          double right = PI/2.0;          while(right-left > eps)          {              double mid = (right+left)/2.0;              double rmid = (mid+right)/2.0;              double xp1 = Del(mid);              double xp2 = Del(rmid);              if(xp1 > xp2) right = rmid;              else left = mid;              Max = max(Max, max(xp1, xp2));          }          if(Max > y) cout<<"no"<<endl;          else cout<<"yes"<<endl;      }  }  

以车长为玄长,画四分之一圆,以此圆心为圆心,此圆半径减去车宽为半径再画四分之一圆。如果路拐角小圆之内,为yes,否则为no,如图:

#include <iostream> #include<time.h> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<string> #include<cmath> #include<map> #define eps 1e-10 #define PI acos(-1) using namespace std; const int maxn = 220; #define LL long long double x, y, l, w; double Del(double ang) { double s = l*cos(ang)+w*sin(ang)-x; double h = s*tan(ang)+w*cos(ang); return h; } int main() { while(cin >>x>>y>>l>>w) { double Max = 0.0; double left = 0; double right = PI/2.0; while(right-left > eps) { double mid = (right+left)/2.0; double rmid = (mid+right)/2.0; double xp1 = Del(mid); double xp2 = Del(rmid); if(xp1 > xp2) right = rmid; else left = mid; Max = max(Max, max(xp1, xp2)); } if(Max > y) cout<<"no"<<endl; else cout<<"yes"<<endl; } } 如上图,这个问题就是一个矩形的一边的2个点分别固定在x和y轴上,该边和x轴的夹角θ在0到π/2的范围内滑动,看另一边所代表的直线y = -tanθ*x+w/cosθ+l*sinθ在θ滑动的过程中会不会滑到点(x,y)的上方 即求f(θ) = w/cosθ+l*sinθ-tanθ*x-y的最大值是否大于0 我的求法是对f(θ)求导,得f'(θ),再用二分法求f'(θ)=0的点θ1,判断f(θ1)是否大于0 使用该思路成功 AC...... 
转载请注明原文地址: https://www.6miu.com/read-16134.html

最新回复(0)