啟發式搜尋 A IDA 演算法詳解

2021-10-02 04:17:14 字數 3331 閱讀 6049

a*大意:利用乙個估價函式h()確定點的遍歷和更新順序從而減少遍歷次數

ida*大意:通過貪心取答案步數,並用於與估價函式剪枝,逐步驗證得出正確答案。

可能看起來有點迷,其實並不難,下面將用誰都不懂通俗易懂的方式講解。

特點是都常用於騙分。

前置芝士:最短路和深搜

相信大家都會。

感覺並不是很需要圖啊。。。

設起點到終點的總費用為f(n),從起點到當前點的已知費用為g(n),預估當前點到終點的費用為h(n)。

顯然我們可以預估f(n)=g(n)+h(n),便得到了乙個總費用的近似值(先不考慮正確性)。

得到近似值之後,便可以加入乙個小根的優先佇列。明顯總費用越小越好,所以先遍歷預估總費用小的點。

第k次到達終點,便是k短路。

**表示:(c++演示

struct data

}priority_queueq;

注意到當前點到終點的費用是預估而不是精確值,與廣搜等遍歷找最小演算法不同,它體現了啟發性,所以是啟發式搜尋。

該演算法保證正確性的條件是h(n)<=h*(n),其中h*(n)為當前點到終點的確定的最小費用,h(n)>=0。

證明:它的最優性質體現在當到達終點時,h(n)<=h*(n)=0,那麼h(n)=0,f(n)=g(n)+h(n)=g(n)+0=f*(n),其中f*(n)為真正的總費用,即f(n)就為最短路徑。

(參考:

其中當h(n)越靠近h*(n),效率越優秀。這一點可以感性理解,越靠近真實值就越準確(證明可以買專業書看

所以a*演算法的執行效率取決於估價函式的優劣。

同樣的,a*也可以用於求k短路問題。

因為高效率,我們可以一直跑,直到第k次到達終點,即為k短路。

當然,我們既然能夠跑多次,那麼跑一次最短路綽綽有餘。我們不如從終點往回用dijkstra等演算法得到終點到每個點的距離,即每個點的h*(n),此時估價函式與實際距離相同,必然最優。

這是另外一種方向,但仍要用到上面所說的f(n),g(n),和h(n)。

我們不再直接得到費用,而是採取貪心的方法預設乙個總費用,並驗證是否可行,不可行就增大這個費用,重複操作,直到找到乙個可行的費用為止,該費用就是答案(十分暴力

有了這個總費用,相當於給你的演算法加了乙個天花板,限制了天馬行空的列舉。

用**的形式寫出來就是:

if(g

(n)+

h(n)

>

f(n)

)return

;

但別小看這一句,它能大大優化爆搜,使複雜度變得玄學而通過。

h(n)一般每個狀態都計算一遍或者從上乙個狀態轉移。

常用於資料量在兩位數以內的爆搜題。

在求k短路時,可以設定乙個陣列限制每個點只能到達k次,因為已經是到點x的k短路了,再從x走到終點必然最優也是k短路,所以每個點到達k次以上沒有意義,可以剪枝。

1. a* 洛谷 p4467 [scoi2007]k短路

沒有辦法,出題人又卡a*。。。

#include

using

namespace std;

int e1[

10010

],w1[

10010

],nxt1[

10010

],head1[

110]

,cnt1;

int e2[

10010

],w2[

10010

],nxt2[

10010

],head2[

110]

,cnt2;

int dis[

110]

,n,m,k,a,b;

bool vis[

110]

;struct data1};

priority_queueq1;

struct data2};

priority_queueq2;

void

add1

(int x,

int y,

int z)

void

add2

(int x,

int y,

int z)

void

dijkstra()

);while

(!q1.

empty()

));}

}}}void

astar()

);//1ll狀壓,不能走重複點

while

(!q2.

empty()

)if(cnt==k)

return;}

for(

int i=head2[u.x]

;i;i=nxt2[i])}

printf

("no");

}int

main()

for(

int i=

1;i<=m;i++

)dijkstra()

;astar()

;}

2. ida* 洛谷p2324 [scoi2005]騎士精神
#include

using

namespace std;

int a[6]

[6],maxn,t;

int b[6]

[6]=

,,,,

,};int dx[8]

=;int dy[8]

=;bool

dfs(

int t,

int x,

int y,

int mn,

int fa)

return0;

}int

main()

else a[i]

[j]=ch-

'0';

if(a[i]

[j]!=b[i]

[j]) minn++;}

bool yes=0;

for(

int i=minn;i<=

16;i++)}

if(yes==0)

printf

("-1\n");

}}

洛谷p2483 k短路 / [sdoi2010]魔法豬學院

poj1084(dlx+ida*) 見另一篇部落格:

poj3523

poj2032

uva10181

uva11212

uva1343

uva1602

uva10384

poj3134

hdu1560

hdu1667

A 演算法(啟發式搜尋)

a 演算法,a a star 演算法是一種靜態路網中求解最短路徑最有效的直接搜尋方法,也是解決許多搜尋問題的有效演算法。演算法中的距離估算值與實際值越接近,最終搜尋速度越快。別稱 啟發式搜尋 表示式 f n g n h n f n g n h n f n g n h n 公式表示為 f n g n ...

啟發式搜尋

啟發式搜尋 heuristically search 又稱為有資訊搜尋 informed search 它是利用問題擁有的啟發資訊來引導搜尋,達到減少搜尋範圍 降低問題複雜度的目的,這種利用啟發資訊的搜尋過程稱為啟發式搜尋。例題 八數碼問題 運用優先佇列,根據目前已經確定的位置算出目前的價值,並匯入...

啟發式搜尋

啟發式搜尋 啟發式搜尋就是在狀態空間中的搜尋對每乙個搜尋的位置進行評估,得到最好的位置,再從這個位置進行搜尋直到目標。這樣可以省略大量無謂的搜尋路徑,提高了效率。在啟發式搜尋中,對位置的估價是十分重要的。採用了不同的估價可以有不同的效果。在啟發式搜尋中,我們每次找到當前 最有希望是最短路徑 的狀態進...