HDU 2438 Turn the corner(三分)

昨天个人赛的题目,没有做出来,今天学了一下三分,其实很简单,就是用来求一个凸函数或凹函数的最值的方法。

大家可以看这个博客,讲的很清楚 :点击打开链接

然后该题就是设拐的角度为自变量,范围0~pi/2 。 然后三分就行了。   这样就可以求出最大值是多少了,然后如果最值比y小,就可以过去,否则不可以。

值得一提的是,队里有人用暴力过了,他将拐点设在了车的中间(l/2处),然后暴力的转角,每次增加0.0001度来判断的,其实我觉得这样肯定不对,因为拐点不一定在车的中间,反例很容易找到。   而我们在三分求最值的时候,是默认的车的后边紧贴着墙的,所以这样就只需要考虑车前边是不是会碰到墙就行了,构造这样的一个函数很容易证明其是一个凸函数,当然有一点比较坑的是x和y有可能小于车宽,我想知道如果x小于车宽,车是怎么停在x里的?2333。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<numeric>
#include<functional>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<cassert>
#include<complex>
#include<iomanip>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-7;
const int INF = 1000000000;
const int maxn = 100;
double x,y,l,w;
double C(double m) {
    double s = l*sin(m) + w*cos(m) - x;
    double h = s/tan(m) + w*sin(m);
    return h;
}
int main() {
    while(~scanf("%lf%lf%lf%lf",&x,&y,&l,&w)) {
        double L = 0, R = PI/2, mid , mmid;
        if(x < w || y < w) { printf("no\n"); continue; }
        while(R-L > eps) {
            mid = (L+R)/2;
            mmid = (mid+R)/2;
            if(C(mid) > C(mmid)) R = mmid;
            else L = mid;
        }
        double h = C(mid);
        if(h < y || fabs(h - y) < eps) printf("yes\n");
        else printf("no\n");
    }
    return 0;
}


你可能感兴趣的:(HDU,三分,ACM-ICPC)