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 它是利用問題擁有的啟發資訊來引導搜尋,達到減少搜尋範圍 降低問題複雜度的目的,這種利用啟發資訊的搜尋過程稱為啟發式搜尋。例題 八數碼問題 運用優先佇列,根據目前已經確定的位置算出目前的價值,並匯入...
啟發式搜尋
啟發式搜尋 啟發式搜尋就是在狀態空間中的搜尋對每乙個搜尋的位置進行評估,得到最好的位置,再從這個位置進行搜尋直到目標。這樣可以省略大量無謂的搜尋路徑,提高了效率。在啟發式搜尋中,對位置的估價是十分重要的。採用了不同的估價可以有不同的效果。在啟發式搜尋中,我們每次找到當前 最有希望是最短路徑 的狀態進...