關於求函式極值,通常有二分、三分、爬山、模擬退火等。
當然,不同的演算法適應不同的函式型別,比如上述4種演算法的前三種通常用來處理單峰函式,其中爬山演算法也可以處理多峰函式,但是容易陷入區域性最優解。
當然,爬山演算法和模擬退火演算法都屬於隨機化演算法(騙分用的),所以不要總是使用。
這個演算法但凡學過oi的人應該都會的,求最值的操作也很簡單。
不必多講,上例題:
codeforces round #700 searching local minimum
這是一道互動題,題面意思大概就是有乙個未知的陣列,給定長度 $ n $ , 每次可以詢問該陣列的任意乙個位置的數, 在詢問次數不超過 $ 100 $ 的
情況下求出該陣列的local minimum $ k $ 。 其中若 $ a_i < min (a_, a_) $ ,則 $ k = i $ 。
保證該陣列僅存在乙個 $ k $, 且 $ a_0 = a_ = +\infty $ 。
其實這個題的思路也類似於三分了, 由於該函式實質上是乙個散點型函式,所以我們每次比較 $ mid $ 和 $ mid + 1 $ 即可。
具體細節看**:
#include#include#include#includeint n;
template inline void read(i &x) while(ch < '0' || ch > '9');
do while(ch >= '0' && ch <= '9');
x *= f; return;
}int binary_search(void)
return l;
}int main()
上個題的思想本質上就是三分了。 通常三分的分段方法是: 取 $ l $ 和 $ r $ 的中點 $ mid $ ,再取 $ mid $ 和 $ r $ 的中點 $ mmid $, 以此將
求解區間分成3段。然後與上個題的思路類似,每次縮小求解區間,最後得出答案。
需要注意的是,三分通常運用在正常的連續函式上,所以三分的控制條件一般設為 $ l + esp < r$ 。 \(esp\) 按照題目的精度要求來取,一般情況下 \(1e-6\) 左右。
由於爬山演算法能完成的任務完全可以由三分或者更優秀的模擬退火取代,所以這裡不多介紹。
skip
模擬退火這種演算法,相較於爬山演算法的優點就是在求解過程中有一定概率接受乙個相較於當前最優解而言更劣的解。所以,這就在一定程度上大大減少了演算法陷入區域性最優解的可能。
我們定義當前溫度為 $ t $ ,新狀態與已知狀態(由已知狀態通過隨機的方式得到)之間的能量(值)差為 $ \delta e $,則發生狀態轉移(修改最優解)的概率為 :
1.新狀態更優,概率為 $ 1 $。
2.新狀態更劣,概率為 $ e^} $。
注意:我們有時為了使得到的解更有質量,會在模擬退火結束後,以當前溫度在得到的解附近多次隨機狀態,嘗試得到更優的解(其過程與模擬退火相似)。
模擬退火時我們有三個引數:初始溫度 $ t_0 $,降溫係數 $ d $ ,終止溫度 $ t_k$ 。其中 $ t_0 $是乙個比較大的數, $ d $是乙個非常接近 $ 1 $ 但是小於 $ 1 $ 的數。
首先讓溫度 $ t = t_0 $,然後按照上述步驟進行一次轉移嘗試,再讓 $ t = t \times d $。當 $ t \leq t_k $ 時模擬退火過程結束,當前最優解即為最終的最優解。
注意為了使得解更為精確,我們通常不直接取當前解作為答案,而是在退火過程中維護遇到的所有解的最優值。
咋寫呢?以 luogu p1337 為例(**摘自oi-wiki):
#include #include #include const int n = 10005;
int n, x[n], y[n], w[n];
double ansx, ansy, dis;
double rand()
double calc(double xx, double yy)
if (res < dis) dis = res, ansx = xx, ansy = yy;
return res;
}void simulateanneal()
for (int i = 1; i <= 1000; ++i)
}int main()
ansx /= n, ansy /= n, dis = calc(ansx, ansy);
simulateanneal();
printf("%.3lf %.3lf\n", ansx, ansy);
return 0;
}
matlab求極值的函式
sign函式 當x 0時,sign x 1 當x 0時,sign x 0 當x 0時,sign x 1。diff函式 diff x 表示x相鄰的元素之差。設z是要分析的資料的集合。由數學知識知道,f x 在x0的某鄰域內連續,且在空心鄰域內有導數,當x由小到大通過x0時,1 f x 左正右負,則 f...
簡單遺傳演算法求函式極值
引言 遺傳演算法求函式極值算是遺傳演算法的一種最簡單的應用,這裡就介紹一種簡單的,全文基本翻譯自codeproject的一篇文章,作者為luay al wesi,軟體工程師。例子中的函式為y x2 5 大家可以將其改為其他複雜一些的函式,比如說f x 10sin 5x 7cos 4x 等。本篇文章適...
python 遺傳演算法求函式極值問題
遺傳演算法實現求函式極大值 zjh import numpy as np import random import matplotlib.pyplot as plt class ga 求出二進位制編碼的長度 def init self self.boundsbegin 2 self.boundsen...