將整個搜尋過程分成兩半,分別搜尋,最後將兩半的結果合併。由於搜尋的複雜度往往是指數級的,而折半搜尋可以使指數減半,也就能使複雜度開方。
有n 盞燈,每盞燈與若干盞燈相連,每盞燈上都有乙個開關,如果按下一盞燈上的開關,這盞燈以及與之相連的所有燈的開關狀態都會改變。一開始所有燈都是關著的,你需要將所有燈開啟,求最小的按開關次數。
?分析如果這道題暴力 dfs 找開關燈的狀態,時間複雜度就是 o(2^n), 顯然超時。不過,如果我們用meet-in-middle的話,時間複雜度可以優化至 o(n2^(n/2))。meet-in-middle就是讓我們先找一半的狀態,也就是找出只使用編號為 1到mid 的開關能夠到達的狀態,再找出只使用另一半開關能到達的狀態。如果前半段和後半段開啟的燈互補,將這兩段合併起來就得到了一種將所有燈開啟的方案。具體實現時,可以把前半段的狀態以及達到每種狀態的最少按開關次數儲存在 map 裡面,搜尋後半段時,每搜出一種方案,就把它與互補的第一段方案合併來更新答案。
c++
#include #include #include #include using namespace std;
typedef long long ll;
int n, m, ans = 0x7fffffff;
mapf;
ll a[40];
int main()
for (int i = 0; i < (1 << (n / 2)); ++i)
}if (!f.count(t))
f[t] = cnt;
else
f[t] = min(f[t], cnt);
} for (int i = 0; i < (1 << (n - n / 2)); ++i)
}if (f.count(((1ll << n) - 1) ^ t))
ans = min(ans, cnt + f[((1ll << n) - 1) ^ t]);
} cout << ans;
return 0;
}
啟發式搜尋就是對取和不取都做分析,從中選取更優解(或刪去無效解)
輔助資訊
所求解問題之外、與所求解問題相關的特定資訊或知識
評價函式(evaluation function)f(n)
從當前節點n出發,根據評價函式來選擇後續節點
啟發函式(heuristic function) h(n)
計算從節點n到目標節點之間所形成路徑的最小代價值。這裡將兩點之間的直線距離作為啟發函式。
辰辰是個天資聰穎的孩子,他的夢想是成為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了乙個難題。醫師把他帶到乙個到處都是草藥的山洞裡對他說:「孩子,這個山洞裡有一些不同的草藥,採每一株都需要一些時間,每一株也有它自身的價值。我會給你一段時間,在這段時間裡,你可以採到一些草藥。如果你是乙個聰明的孩子,你應該可以讓採到的草藥的總價值最大。」
如果你是辰辰,你能完成這個任務嗎?
輸入格式
第一行有 22 個整數 tt(1 \le t \le 10001≤t≤1000)和 mm(1 \le m \le 1001≤m≤100),用乙個空格隔開,tt 代表總共能夠用來採藥的時間,mm 代表山洞裡的草藥的數目。
接下來的 mm 行每行包括兩個在 11 到 100100 之間(包括 11 和 100100)的整數,分別表示採摘某株草藥的時間和這株草藥的價值。
輸出格式
輸出在規定的時間內可以採到的草藥的最大總價值。
?分析我們寫乙個估價函式f ,可以剪掉所有無效的0 枝條(就是剪去大量無用不選枝條)。
估價函式f的執行過程如下:
我們在取的時候判斷一下是不是超過了規定體積(可行性剪枝)。
在不取的時候判斷一下不取這個時,剩下的藥所有的價值 + 現有的價值是否大於目前找到的最優解(最優性剪枝)。
c++
#include #include using namespace std;
const int n = 105;
int n, m, ans;
struct node node[n];
bool operator<(node p, node q)
int f(int t, int v) else
return (int)(tot + v * node[t + i].f);
return tot;
}void work(int t, int p, int v)
int main()
sort(node + 1, node + n + 1);
work(1, m, 0);
printf("%d\n", ans);
return 0;
}
評價函式f(n)=啟發函式h(n)
定義評價函式:f(n)= g(n)+ h(n)
評估函式 = 當前最小開銷代價 + 後續最小開銷代價
為了保證a*演算法是最優(optimal),需要啟發函式h(n)是可容的(admissibleheuristic)和一致的(consistency,或者也稱單調性,即monotonicity)
最優不存在另外乙個解法能得到比a*演算法所求得解法具有更小開銷代價。
可容(admissible)
專門針對啟發函式而言,即啟發函式不會過高估計(over-estimate)從節點n到目標結點之間的實際開銷代價(即小於等於實際開銷)。如可將兩點之間的直線距離作為啟發函式,從而保證其可容。
一致性(單調性)
假設節點n的後續節點是n』,則從n到目標節點之間的開銷代價一定小於從n到n』的開銷再加上從n』到目標節點之間的開銷,即h(n)≤c(n,a, n』)+ h(n』)。這裡n』是n經過行動a所抵達的後續節點,c(n, a,n』)指n』和n之間的開銷代價。
其實…… h = 0時就是 dfs演算法, 並且h = 0邊權為 1時就是 bfs
例如:起始位置是a,目標位置是p,字母後的數字表示節點的估價值
搜尋過程中設定兩個表:open和closed。open表儲存了所有已生成而未考察的節點,closed表中記錄已訪問過的節點。演算法中有一步是根據估價函式重排open表。這樣迴圈中的每一步只考慮open表中狀態最好的節點。具體搜尋過程如下:
初始狀態:
open=[a5];closed=;
2)估算a5,取得搜有子節點,並放入open表中;
open=[b4,c4,d6];closed=[a5]
3)估算b4,取得搜有子節點,並放入open表中;
open=[c4,e5,f5,d6];closed=[b4,a5]
4)估算c4;取得搜有子節點,並放入open表中;
open=[h3,g4,e5,f5,d6];closed=[c4,b4,a5]
5)估算h3,取得搜有子節點,並放入open表中;
open=[o2,p3,g4,e5,f5,d6];closed=[h3,c4,b4,a5]
6)估算o2,取得搜有子節點,並放入open表中;
open=[p3,g4,e5,f5,d6];closed=[o2,h3,c4,b4,a5]
7)估算p3,已得到解;
看一下偽**
best_first_search()
for(每乙個x的子節點y)
//還沒有排序
else
if(y在open表中)
else
//y在close表中
} 將x節點插入close表中;
按照估價值將open表中的節點排序;
}//end for
}//end while
}//end func
?經典例子:八數碼(我也不懂。。)
在 3 x3的棋盤上,擺有八個棋子,每個棋子上標有 1至8 的某一數字。棋盤中留有乙個空格,空格用 0來表示。空格周圍的棋子可以移到空格中,這樣原來的位置就會變成空格。給出一種初始布局和目標布局(為了使題目簡單,設目標狀態如下),找到一種從初始布局到目標布局最少步驟的移動方法。
123
804765
h 函式可以定義為,不在應該在的位置的數字個數。
容易發現h 滿足以上兩個性質,此題可以使用 a*演算法求解。
#include #include #include #include #include using namespace std;
const int dx[4] = , dy[4] = ;
int fx, fy;
char ch;
struct matrix
} f, st;
int h(matrix a)
struct node
} x;
priority_queueq;
sets;
int main()
q.push();
while (!q.empty())
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
if (!x.a.a[i][j]) fx = i, fy = j;
for (int i = 0; i < 4; i++) );
swap(x.a.a[fx][fy], x.a.a[xx][yy]);}}
} return 0;
}
前端演算法系列 搜尋
遍歷陣列,找到跟目標相等的元素,就返回它的下標,遍歷結束後,沒找到就返回 1 時間複雜度 o n 迴圈 array.prototype.sequentialsearch function item return 1 const arr 5 4,3 2,1 arr.sequentialsearch 3...
滲透神器系列 搜尋引擎
搜尋引擎是我日常工作中用得最多的一款工具,國內常用的搜尋引擎包括baidu,sougou,bing等。但我本篇要紀錄的並不是這些常用的搜尋引擎,而是資訊保安從業人員必備的幾款網路搜尋引擎。本篇要介紹的搜尋引擎包括 shodan,censys,鍾馗之眼,google,fofa,dnsdb等。介紹的內容...
享受工作系列 人生演算法 活在套路裡
當下中國最好的生意 這兩張圖之間存在著一種對應關係,標準化的成功對應的標準化的服務,非常符合市場規律,是一套相對完整的正向迴圈體系。這些也傳達了乙個資訊,實現財務自由是有階段的,不是所有人都能到達終極階段,而且即使到了最高端階段,人生未必自由,每個階段都人群都被各種稀缺驅趕著,每個階段的人都有每個階...