学习博客:
https://www.cnblogs.com/zwfymqz/archive/2018/04/28/8966901.html
https://blog.csdn.net/baimafujinji/article/details/6474567
https://www.cnblogs.com/caijiaming/p/11674182.html
https://www.cnblogs.com/cieusy/p/9871095.html
https://blog.csdn.net/qq_18343569/article/details/50300147
模拟退火
定义:
模拟退火算法(Simulate Anneal,SA)是一种通用概率演算法,用来在一个大的搜寻空间内找寻命题的最优解
变量:
T:当前温度,从高温到低温,也就是从不稳定状态到稳定状态,代表算法进行到了什么程度
ΔT:每次的温度变化率,一般取0.95-0.99,模拟退火过程,上次的温度×ΔT=当前的温度
算法流程:
①:枚举温度T
②:计算下一步的状态
③:若下一步的状态比当前状态优或者满足进行转移的条件就进行转移
④:降温
1:Country Meow
题意:
求三维坐标下包围n个点的最小的球的半径
题解:
每次找到一个距离当前点最远的点,作为可转移的下一个状态,
概率Δp=(据当前位置最远的点-当前点的位置)/初始状态
代码
//#include
#include
#include
#include
#include
#include
#include
#include
旅行商问题:
还不会,直接放网上找的代码了,当模板用了
#include
#include
#include
using namespace std;
#define MAX_CITY_NUM 100
#define T0 2000
#define T 1e-5
#define ALPHA 0.98
#define L 20000
struct path{
int route[MAX_CITY_NUM];
double dis;
};
double w[MAX_CITY_NUM][MAX_CITY_NUM];
int num;
double s = 0;
path p0;
void Init_City()
{
cout << "Please input the number of cities:" << endl;
cin >> num;
for (int i = 0; i < num; ++i)
for (int j = 0; j < num; ++j)
cin >> w[i][j];
}
void Init_path()
{
p0.dis = 0;
for (int i = 0; i < num; ++i)
{
p0.route[i] = i;
if (i != num - 1)
p0.dis += w[i][i + 1];
}
p0.dis += w[num - 1][0];
}
path generate(path p)
{
int x = 0, y = 0;
while (x == y)
{
x = (int)(num * (rand() / (RAND_MAX + 1.0)));
y = (int)(num * (rand() / (RAND_MAX + 1.0)));
}
path gen = p;
int tmp;
tmp = gen.route[x];
gen.route[x] = gen.route[y];
gen.route[y] = tmp;
gen.dis = 0;
for (int i = 0; i < num - 1; ++i)
gen.dis += w[gen.route[i]][gen.route[i + 1]];
gen.dis += w[gen.route[num - 1]][gen.route[0]];
return gen;
}
void TSP_SA()
{
double t = T0;
srand(time(NULL));
path cur = p0;
path next = p0;
int bChange;
while (t > T)
{
bChange = 0;
for (int i = 0; i < L; ++i)
{
next = generate(cur);
double df = next.dis - cur.dis;
if (df <= 0)
{
cur = next;
bChange = 1;
}
else
{
double rndp = rand() / (RAND_MAX + 1.0);
double eps = exp(-df / t);
if (eps > rndp && eps < 1)
{
cur = next;
bChange = 1;
}
}
}
if (cur.dis < p0.dis)
p0 = cur;
t *= ALPHA;
if (!bChange)
++s;
else
s = 0;
if (s == 2)
break;
}
}
int main()
{
Init_City();
Init_path();
TSP_SA();
cout << "The best path is:" << endl;
for (int i = 0; i < num; ++i)
cout << p0.route[i] << " -> ";
cout << p0.route[0] << endl;
cout << "The distance of the best path is: " << p0.dis << endl;
system("pause");
return 0;
}
3:多项式最值问题:
还是不会,回头填坑。。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define ITERS 10
#define T 100
#define eps 1e-8
#define delta 0.98
#define INF 1e99
double x[ITERS];
int judge(double x, double y)
{
if (fabs(x - y) < eps) return 0;
return x < y ? -1 : 1;
}
double random()
{
double x = rand()*1.0 / RAND_MAX;
if (rand() & 1) x *= -1;
return x;
}
double F(double x, double y)
{
return 6 * pow(x, 7) + 8 * pow(x, 6) + 7 * pow(x, 3) + 5 * pow(x, 2) - x*y;
}
void init()
{
for (int i = 0; i < ITERS; i++)
{
x[i] = fabs(random()) * 100;
}
}
double sa(double y)
{
double ans = INF;
double t = T;
while (t < eps)
{
for (int i = 0; i < ITERS; i++)
{
double tmp = F(x[i], y);
for (int j = 0; j < ITERS; j++)
{
double _x = x[i] + random()*t;
if (judge(_x, 0) >= 0 && judge(_x, 100) <= 0)
{
double f = F(_x, y);
if (tmp>f)
x[i] = _x;
}
}
}
t = t*delta;
}
for (int i = 0; i < ITERS; i++)
{
ans = min(ans, F(x[i], y));
}
return ans;
}
int main()
{
int t;
cin >> t;
while (t--)
{
double y;
cin >> y;
srand(time(NULL));
init();
cout << sa(y) << endl;
}
return 0;
}