模拟退火算法

来源:互联网 发布:虚拟机网络上有重名 编辑:程序博客网 时间:2024/06/14 07:01
一些求解极值的问题不能通过函数特性直接求解,只能暴力枚举,但是单纯的枚举效率不高,通过模拟退火算法可以高效的找到答案。
学习好博文:
http://www.cnblogs.com/heaad/archive/2010/12/20/1911614.html

相关题目:
最小圆覆盖:
hdu 3007 Buried memory
http://acm.hdu.edu.cn/showproblem.php?pid=3007
大意:给出一些点,求出能覆盖他们的最小的圆。输出圆心和半径

#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>using namespace std;const double eps=1e-7,INF=1e99; // T: 初始温度  delta:下降速率const double T=10,delta=0.88;    //一般地,T=100, delta=0.98const int N=5e2+10;struct point{    double x,y;}p[N],s;double dis(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}double solve(int n){    s=p[0];    double t=T;    double r=INF;    while(t>eps){        int k=0;        double d=0;        for(int i=0;i<n;i++){            double f=dis(s,p[i]);            if(f>d){                d=f;                k=i;            }        }        s.x+=(p[k].x-s.x)/d*t;        s.y+=(p[k].y-s.y)/d*t;        r=min(r,d);        t*=delta;    }    return r;}int main(){    int n;    while(~scanf("%d",&n)&&n){        for(int i=0;i<n;i++){            scanf("%lf %lf",&p[i].x,&p[i].y);        }        double r=solve(n);        printf("%.2lf %.2lf %.2lf\n",s.x,s.y,r);    }    return 0;}

最小球包含
POJ 2069 Super Star
http://poj.org/problem?id=2069
大意:给出一些三维空间的点,求最小的包含他们的球的半径

#include <iostream>#include <cstdio>#include <cmath>using namespace std;const double T=100,delta=0.98; //下降速度一般设成0.98const double eps=1e-7,INF=1e99;struct point{    double x,y,z;}p[35],s;double dis(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));}double solve(int n){    s=p[0];    double t=T;    double ans=INF;    while(t>eps){        int k=0;        for(int i=0;i<n;i++){            if(dis(s,p[i])>dis(s,p[k])){                k=i;            }        }        double d=dis(s,p[k]);        ans=min(ans,d);        s.x+=(p[k].x-s.x)/d*t;  //向量        s.y+=(p[k].y-s.y)/d*t;        s.z+=(p[k].z-s.z)/d*t;        t*=delta;    }    return ans;}int main(){    int n;    while(cin>>n&&n){        for(int i=0;i<n;i++){            scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);        }        printf("%.5lf\n",solve(n));    }    return 0;}

查找函数极值:
hdu 2899 Strange fuction
http://acm.hdu.edu.cn/showproblem.php?pid=2899
求解: F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100) 的最小值

#include <iostream>#include <cstdio>#include <cmath>#include <stdlib.h>#include <algorithm>using namespace std;const double eps=1e-7,INF=1e99;const double T=100,delta=0.88;  // 0.98 太慢了const int N=10;double x[N];double random(){    double x=rand()*1.0/RAND_MAX;    if(rand()&1) x=-x;    return x;}int jud(double a,double b){    if(fabs(a-b)<eps) return 0;    if(a-b<-eps) return -1;    return 1;}double calc(double x,double y){    return 6*pow(x,7)+8*pow(x,6)+7*pow(x,3)+5*x*x-y*x;}double solve(double y){    for(int i=0;i<N;i++) x[i]=fabs(random()*100);    double ans=INF;    double t=T;    while(t>eps){        for(int i=0;i<N;i++){ // change x[i]            double temp=calc(x[i],y);            for(int j=0;j<N;j++){  //times                double xx=x[i]+random()*t;                if(jud(xx,0)>=0 && jud(xx,100)<=0){                    if(jud(temp,calc(xx,y))>0){                        x[i]=xx;                        break;                    }                }            }        }        t=t*delta;    }    for(int i=0;i<N;i++) ans=min(ans,calc(x[i],y));    return ans;}int main(){    int t;    double y;    cin>>t;    while(t--){        scanf("%lf",&y);        printf("%.4lf\n",solve(y));    }    return 0;}/*%.4lf\n2100-74.4291200-178.8534-------------%lf\n2100-74.429122200-178.853367*/

本想尝试做三分题,zoj 3421 Error Curves,但是发现不是超时,就是WA。

0 0
原创粉丝点击