Strange Function
題目大意:
函數 F(x) = 6x7 + 8x6 + 7x3 + 5x2 - yx, 其中x的範圍是0 ≤ x ≤ 100.
輸入y值,輸出F(x)的最小值
模擬退火算法
模擬退火就是類似於物體降溫的概率,來進行多次搜索迭代
在迭代過程中,模擬退火算法隨機選擇下一個狀態,有兩種可能
- 新狀態比原來狀態更優,那麼接受這個新狀態
- 新狀態更差,那麼以一定的概率接受該狀態,不過這個概率應該隨着時間的推移逐漸降低
模擬退火算法的主要步驟如下:
- 設置一個初始的溫度T
- 溫度下降,狀態轉移。從當前溫度按降溫係數下降到下一個溫度,在新的溫度計算當前狀態
- 如果溫度降到設定的溫度下界,程序停止
題解代碼
#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-8; // 終止溫度
double y;
double func(double x) // 計算函數值
{
return 6 * pow(x, 7.0) + 8 * pow(x, 6.0) + 7 * pow(x, 3.0) + 5 * pow(x, 2.0) - y * x;
}
double solve(void)
{
double T = 100; // 初始溫度
double delta = 0.98; // 降溫係數
double x = 50.0; // x的初始值
double now = func(x); // 計算初始函數值
double ans = now; // 返回值
while (T > eps) {
int f[2] = {1, -1};
double newx = x + f[rand() % 2] * T; // 按概率改變x,隨t的降溫而減少
if (newx >= 0 && newx <= 100) {
double next = func(newx);
ans = min(ans, next);
if (now - next > eps) {
x = newx;
now = next;
}
}
T *= delta;
}
return ans;
}
int main(void)
{
int cas;
scanf("%d", &cas);
while (cas--) {
scanf("%lf", &y);
printf("%.4lf\n", solve());
}
return 0;
}