三分法——求解凸性函数的极值问题

转自http://hi.baidu.com/vfxupdpaipbcpuq/item/81b21d1910ea729c99ce33db

UVALive 5009

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define  eps 1e-10
#define  hpi asin(1.0)
#define  pi  acos(-1.0)
#define  inf 0x3f3f3f3f
#define  INF 0x3f3f3f3f3f3f3f3fLL
#define  clear(x) memset((x), 0, sizeof(x))
using namespace std;

const int MAXN = 10010;
double a[MAXN], b[MAXN], c[MAXN];
int T, n;

double get_max(double x)
{
    double ans = a[0]*x*x+b[0]*x+c[0];    
    for(int i = 1; i < n; ++i)
    {
        ans = max(ans, a[i]*x*x+b[i]*x+c[i]);
    }
    return ans;
}

int main()
{
    //freopen("aa.in", "r", stdin);
    //freopen("bb.out", "w", stdout);
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        for(int i = 0; i < n; ++i)
        {
            scanf("%lf %lf %lf", &a[i], &b[i], &c[i]);
        }
        double l = 0, r = 1000, m1, m2, r1, r2;
        while(l + eps < r)
        {
            m1 = l + (r - l) / 3.0;
            m2 = r - (r - l) / 3.0;
            r1 = get_max(m1);
            r2 = get_max(m2);
            if(r1 >= r2)
                l = m1;
            else
                r = m2;
        }
        printf("%.4lf\n", get_max(l));
    }
    return 0;
}

POJ 3301

struct Point
{
    double x, y;
    Point() {}
    Point(double t_x, double t_y): x(t_x), y(t_y){}
}p[40];
int T, n;

double get_ans(double angle)
{
    double max_x, max_y, min_x, min_y;
    max_x = max_y = -inf;
    min_x = min_y = inf;
    for(int i = 0; i < n; ++i)
    {
        double t_x = p[i].x * cos(angle) - p[i].y * sin(angle);
        double t_y = p[i].x * sin(angle) + p[i].y * cos(angle);
        if(t_x > max_x)
            max_x = t_x;
        if(t_y > max_y)
            max_y = t_y;
        if(t_x < min_x)
            min_x = t_x;
        if(t_y < min_y)
            min_y = t_y;
    }
    return max((max_x-min_x)*(max_x-min_x), (max_y-min_y)*(max_y-min_y));
}

int main()
{
    //freopen("aa.in", "r", stdin);
    //freopen("bb.out", "w", stdout);

    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        for(int i = 0; i < n; ++i)
        {
            scanf("%lf %lf", &p[i].x, &p[i].y);
        }
        double l = 0, r = asin(1.0), m1, m2;
        while(l + eps < r)
        {
            m1 = l + (r - l) / 3;
            m2 = r - (r - l) / 3;
            if(get_ans(m1) >= get_ans(m2))
                l = m1;
            else
                r = m2;
        }
        printf("%.2lf\n", get_ans(l));
    }
    return 0;
}

HDU 3400

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

//----------------------------------------------------------
#define CL(a,b)       memset(a,b,sizeof(a))
#define CLQ(q)        while(!q.empty())q.pop();
#define FOR(i,a,b)    for(int i=a;i<=b;++i)
#define FD(i,a,b)     for(int i=a;i>=b;--i)
#define FS(i,a)       for(int i=0;a[i];++i)
#define REP(i,n)      for(int i=0;i(b)?(a):(b))
#define min(a,b)      ((a)<(b)?(a):(b))
#define checkMax(a,b) {if(ab)a=b;}
#define READ(a)       freopen(a,"r",stdin)
#define WRITE(a)      freopen(a,"w",stdout)
#define sqr(x)        ((x)*(x))
#define inf           0x3f3f3f3f
#define INF           0x3f3f3f3f3f3f3f3fLL
#define eps           1e-10
typedef long long LL;
const double pi  = acos(-1.0);
const double hpi = asin(1.0);
//-----------------------------------------------------------

struct Point
{
    double x, y;
    Point() {}
    Point(double t_x, double t_y) : x(t_x), y(t_y) {}
    friend istream& operator>> (istream &in, Point &p1)
    {
        in >> p1.x;
        in >> p1.y;
        return in;
    }
}A, B, C, D, P1, P2;
double P, Q, R;

double dis(const Point &p1, const Point &p2)
{
    return sqrt(sqr(p2.x-p1.x)+sqr(p2.y-p1.y));
}

double cal(const Point &p1, const Point &p2)
{
    return dis(A, p1)/P + dis(D, p2)/Q + dis(p1, p2)/R;
}

double cal_time(double lv1, double lv2)
{
    P1.x = A.x + (B.x-A.x)*lv1;
    P1.y = A.y + (B.y-A.y)*lv1;
    P2.x = C.x + (D.x-C.x)*lv2;
    P2.y = C.y + (D.y-C.y)*lv2;
    return cal(P1, P2);
}

double search_CD(double lv)
{
    double low = 0.0, high = 1.0;
    while(low + eps < high)
    {
        double m1 = low + (high - low) / 3.0;
        double m2 = high - (high - low) / 3.0;
        if(cal_time(lv, m1) >= cal_time(lv, m2))
            low = m1;
        else
            high = m2;
    }
    return cal_time(lv, low);
}

double search_AB()
{
    double low = 0.0, high = 1.0;
    while(low + eps < high)
    {
        double m1 = low + (high - low) / 3.0;
        double m2 = high - (high - low) / 3.0;
        if(search_CD(m1) >= search_CD(m2))
            low = m1;
        else
            high = m2;
    }
    return search_CD(low);
}

int main()
{
    //READ("aa.in"); WRITE("bb.out");
    int T;
    scanf("%d", &T);
    while(T--)
    {
        cin >> A;
        cin >> B;
        cin >> C;
        cin >> D;
        cin >> P >> Q >> R;
        printf("%.2lf\n", search_AB());
    }
    return 0;
}

HDU 4717

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

//----------------------------------------------------------
#define CL(a,b)       memset(a,b,sizeof(a))
#define CLQ(q)        while(!q.empty())q.pop();
#define FOR(i,a,b)    for(int i=a;i<=b;++i)
#define FD(i,a,b)     for(int i=a;i>=b;--i)
#define FS(i,a)       for(int i=0;a[i];++i)
#define REP(i,n)      for(int i=0;i(b)?(a):(b))
#define min(a,b)      ((a)<(b)?(a):(b))
#define checkMax(a,b) {if(ab)a=b;}
#define READ(a)       freopen(a,"r",stdin)
#define WRITE(a)      freopen(a,"w",stdout)
#define sqr(x)        ((x)*(x))
#define inf           0x3f3f3f3f
#define INF           0x3f3f3f3f3f3f3f3fLL
#define eps           1e-10
typedef long long LL;
const double pi  = acos(-1.0);
const double hpi = asin(1.0);
//-----------------------------------------------------------

const int MAXN = 360;

struct Point
{
    double x, y;
    double vx, vy;
    Point() {}
    Point(double t_x, double t_y, double t_vx, double t_vy) : x(t_x), y(t_y), vx(t_vx), vy(t_vy) {}
}p[MAXN];
int T, n;

double dis(const Point &p1, const Point &p2)
{
    return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));
}

double cal(double t)
{
    double max_dis = -inf;
    FOR(i, 1, n) FOR(j, 1, n)
    {
        if(i == j) continue;
        double t_dis = dis(Point(p[i].x+p[i].vx*t, p[i].y+p[i].vy*t, 0, 0),Point(p[j].x+p[j].vx*t, p[j].y+p[j].vy*t, 0, 0));
        //cout << t_dis << endl;
        max_dis = max(max_dis, t_dis);
    }
    return max_dis;
}

void solve()
{
    double l = 0, r = 1000000;
    while(l + eps < r)
    {
        double m1 = l + (r - l) / 3.0;
        double m2 = r - (r - l) / 3.0;
        //cout << cal(m1) << " " << cal(m2) << endl;
        if(cal(m1) >= cal(m2))
            l = m1;
        else
            r = m2;
    }
    printf(" %.2lf %.2lf\n", l, cal(l));
}

int main()
{
    //READ("aa.in"); WRITE("bb.out");

    int kcase = 0;
    cin >> T;
    while(T--)
    {
        kcase++;
        cin >> n;
        FOR(i, 1, n)
        {
            cin >> p[i].x >> p[i].y >> p[i].vx >> p[i].vy;
        }
        printf("Case #%d:", kcase);
        solve();
    }
    return 0;
}


你可能感兴趣的:(三分法——求解凸性函数的极值问题)