三分算法解决凸形或者凹形函数的极值;

二分解决具有单调性的函数的极值;

凹形的可以通过*-1转化为凸形

mid = (Left + Right) / 2

midmid = (mid + Right) / 2;

如果mid靠近极值点,则Right = midmid;

否则(即midmid靠近极值点),则Left = mid;

 zoj3203

本题要求影子最长的长度。

在灯、人头、墙角成一条直线时影子长为a,在人到达墙角时影子长为b,我们可以写出人在这两点间时影子的方程:(x*H-D*h)/(x-D)+x,有数学知识可知这个方程在[a,b]之间是凸的,即先增加后减小,有极值,可以用三分法高效求解,注意一些边界条件。

边界x=[0,D/H*h]

#include<cstdio>
#include<iostream>
using namespace std;
#define eps 1e-6
double H,h,D;
double cal(double x)
{
    return (x*H-D*h)/(x-D)+x;
}
void slove()
{
    double left,right,mid,midmid;
    left=0,right=D/H*h;
    while(left+eps<right)
    {
        mid=(left+right)/2;
        midmid=(mid+right)/2;
        if(cal(mid)>=cal(midmid))right=midmid;
        else left=mid;
    }
    printf("%.3lf\n",cal(left));
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lf%lf%lf",&H,&h,&D);
        slove();
    }
    return 0;
}
View Code

 

poj3301

题目要求是求最小的正方形,使之包含所有的点。

在0-90度范围内三分旋转的角度
旋转公式:x’=x*cos(phi)-y*sin(phi) y’=x*sin(phi)+y*cos(phi)

eps=1e-6 wa了,eps=1e-9就AC了,真坑

tip:

pi的表示方法

#define pi 3.1415926535897932384626

const double pi=3.1415926535897932384626;

const double pi=acos(-1.0); poj写成acos(-1) 会编译错误

#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
#define eps 1e-9
#define pi 3.1415926535898
struct ss
{
    double x,y;
}a[50];
int n;
double cal(double angle)
{
    double x1,x2,y1,y2;
    x1=y1=10000;
    x2=y2=-10000;
    for(int i=0;i<n;i++)
    {
        double x=a[i].x*cos(angle)-a[i].y*sin(angle);
        double y=a[i].x*sin(angle)+a[i].y*cos(angle);
        x1=min(x1,x);
        y1=min(y1,y);
        x2=max(x2,x);
        y2=max(y2,y);
    }
    double d=max(y2-y1,x2-x1);
    return -d*d;
}
void slove()
{
    double left,right,mid,midmid;
    left=0;right=pi/2;
    while(left+eps<right)
    {
        mid=(left+right)/2;
        midmid=(mid+right)/2;
        if(cal(mid)>=cal(midmid))right=midmid;
        else left=mid;
    }
    printf("%.2lf\n",-cal(left));
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
        slove();
    }
    return 0;
}
View Code

 

posted on 2015-04-18 10:41  kylehz  阅读(219)  评论(0编辑  收藏  举报