模拟退火算法的改进:
(1)设计合适的状态产生函数,使其根据搜索进程的需要表现出状态的全空间分散性或局部区域性。
(2)设计高效的退火策略。
(3)避免状态的迂回搜索。
(4)采用并行搜索结构。
(5)为避免陷入局部极小,改进对温度的控制方式。
(6)选择合适的初始状态。
(7)设计合适的算法终止准则。
伪代码:
/*
* J(y):在状态y时的评价函数值
* Y(i):表示当前状态
* Y(i+1):表示新的状态
* r: 用于控制降温的快慢,一般为0.9999
* T: 系统的温度,系统初始应该要处于一个高温的状态,一般为100000
* T_min :温度的下限,若温度T达到T_min,则停止搜索,一般为1e-6
*/
while( T > T_min )
{
dE = J( Y(i+1) ) - J( Y(i) ) ;
if ( dE >=0 ) //表达移动后得到更优解,则总是接受移动
Y(i+1) = Y(i) ; //接受从Y(i)到Y(i+1)的移动
else
{
// 函数exp( dE/T )的取值范围是(0,1) ,dE/T越大,则exp( dE/T )也
if ( exp( dE/T ) > random( 0 , 1 ) )
Y(i+1) = Y(i) ; //接受从Y(i)到Y(i+1)的移动
}
T = r * T ; //降温退火 ,0<r<1 。r越大,降温越慢;r越小,降温越快
/*
* 若r过大,则搜索到全局最优解的可能会较高,但搜索的过程也就较长。若r过小,则搜索的过程会很快,但最终可能会达到一个局部最优值
*/
i ++ ;
}
可能需要的代码
double random(int l,int r)//产生随机小数
{
int a=rand(),b=rand()+1;
double ans=(double)a/b;
while(ans>r||ans<l)//可以取到l和r,加上等号则无法取到 l和r
{
a=rand(),b=rand()+1;
ans=(double)a/b;
}
return ans;
}
double T=100000,p=0.9999;//模拟退火的初始温度T,退火率p
srand((unsigned)time(NULL));
例题:
#include<bits/stdc++.h>
#define ll long long int
using namespace std;
ll pow(int a,ll b)
{
ll sum=1;
for(int i=0;i<b;i++)
{
sum*=a;
}
return sum;
}
double random(int l,int r)
{
int a=rand(),b=rand()+1;
double ans=(double)a/b;
while(ans>r||ans<l)//可以取到l和r,加上等号则无法取到 l和r
{
a=rand(),b=rand()+1;
ans=(double)a/b;
}
return ans;
}
int main()
{
srand((unsigned)time(NULL));
ll a,b,MAX,k=0; //MAX最大值,k为a的位数
cin>>a>>b;
MAX=0;
ll m=a;
while(m)//计算a的位数
{
m=m/10;
k++;
}
k++;//需要取1~k位
double T=100000,p=0.9999;//模拟退火的初始温度T,退火率p
if(k==2)//只有一位数的时候,直接输出
{
cout<<a<<endl;
}
else
{
while(T>1e-6)
{
ll a1=rand()%k,a2=rand()%k;
if((a1==a2||a1==0||a2==0)&&k>2) continue;//防止与自身交换,并且剩余不确定的位数多余1
if(a2>a1)//保证a1>a2
{
ll temp=a1;
a1=a2;
a2=temp;
}
ll k1,k2;//交换第a1和a2位
k1=a%pow(10,a1)/pow(10,a1-1)*pow(10,a2-1);
k2=a%pow(10,a2)/pow(10,a2-1)*pow(10,a1-1);
a=a/pow(10,a1)*pow(10,a1)+a%pow(10,a1-1)/pow(10,a2)*pow(10,a2)+a%pow(10,a1-1)%pow(10,a2-1);
a=a+k1+k2;//交换后的a
if(a>MAX&&a<=b)//贪心,选最优
{
MAX=a;
if(a/pow(10,k-2)==b/pow(10,k-2)&&k>2)//如果最高为相同,则不再交换最高位
{
k--;
}
}
else
{
double t=exp(-T);
if(t<random(0,1))//如果找到比当前更差的解,以一定概率接受该解,并且这个概率会越来越小
{
a=a;
}
else
{
a=MAX;
}
}
T=T*p;//退火
}
cout<<MAX<<endl;
}
return 0;
}