[hdu2899]Strange fuction

来自FallDream的博客,未经允许,请勿转载,谢谢。


题意:T组数据,每次给定y,求F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100) 的最小值  T<=100

 

这题貌似是有正常解法的,就是求导之后二分 然而我不会求导 所以呢  上模拟退火

模拟退火呢 大概是说我有一个初始温度,并且以一定的比率衰减。对于每一个状态,向外扩展状态(温度越大扩展范围越大),如果它比目前的状态更优,那么就选择它,不然,以一定的比率接受它(显然答案越劣这个比率越小).

然后时间不会很卡,可以多退火几次,比较稳健,但是它的常数还是挺大的233...

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cmath>
#include<algorithm>
#define INF 1e18
#define T 100
#define delta 0.98
#define eps 1e-8
#define IT 5
using namespace std;

int qq;
double ans;

inline double calc(double x,double y)
{
    double sq=x*x,cube=x*x*x;
    return 6*cube*cube*x+8*cube*cube+7*cube+5*sq-y*x;
}

inline double Ran(){return (double)rand()/(double)RAND_MAX;}

bool check(double x){return x+eps>0&&x<100+eps;}

double search(double y)
{
    double x=Ran()*100,res=calc(x,y),t=T;
    while(t>eps)
    {
        for(int j=1;j<=IT;j++)
        {
            double nx=x+(rand()&1?1:-1)*Ran()*t;
            if(check(nx))
            {
                double th=calc(nx,y);
                if(th<res||Ran()>=exp(-th/res)) res=th,x=nx;
            }
        }
        t*=delta;
    }
    return res;
}

int main()
{
    srand(20170415U);
    for(cin>>qq;qq;--qq)
    {
        double y;ans=INF;
        scanf("%lf",&y);
        for(int i=1;i<=IT;i++)
            ans=min(ans,search(y));
        printf("%0.4lf\n",ans);
    }
    return 0;
}

 

posted @ 2017-04-15 18:32  FallDream  阅读(284)  评论(0编辑  收藏  举报