2020.07.21-11:40[a problem]如果讓你在這麼乙個方格圖中尋找最短路徑,你會怎麼做?2020.08.30-16:55
student-a:我會廣度優先演算法!
student-b[最優]:我會貪心走過去!
上面是最簡單的狀況,如果有障礙物呢?
注:綠色格仔不可通過
student-a:我會廣度優先演算法與深度優先演算法!
student-b:我。。
看起來此問題得到了解決,但是我們可以很快想到:樸素的搜尋演算法最壞情況下竟需要遍歷整個圖!!
那麼我們此時需要剪枝,那麼如何剪呢?
最容易想到的就是在某一步發現不管怎麼樣,都不可能達到目標情況或不是最優解,此時直接回溯,效率提高不少
用乙個式子來表示就是:
\(s+h(s)>dep\)
\(s\)就是當前的步數,\(dep\)就是目標
那麼其中的\(h(s)\)就是對當前的乙個估計,稱為估價函式
當前步數+估計》目標,你還會走下去嗎?
當然不會,所以直接回溯
容易發現,估價函式越準確,\(s\)越小,程式越快;估計函式越不准,\(s\)越大,程式越慢
在尋找最短路的問題中,\(h(s)\)就是代表當前到終點的距離
在不同的問題中,\(h(s)\)也有不同的含義
這裡的\(h(s)\)就是沒有在正確位置上的數的個數
首先計算\(dep\),即最少幾步即可到達目標狀況
隨著廣度的放寬,慢慢進行a*搜尋尋找答案
函式中
if(!dis) return 1;
if(s+dis>stdep) return 0;
就是a*的核心
#include#include#define r register
int goalx[9]=,movx[4]=,zx;
int goaly[9]=,movy[4]=,zy;
int stdep;
std::string begin;
inline int abs(int a)
inline int getrow(int a)
inline int getcolumn(int a)
inline int getoriginal(int x,int y)
inline int getdist(std::string a)
std::swap(begin[past],begin[now]);
if(a_star(s+1,past))
return 1;
std::swap(begin[past],begin[now]);
zx-=movx[i],zy-=movy[i];
} return 0;
}signed main()
std::cout同上,這裡的\(h(s)\)是沒有在正確位置上的棋子的個數
#include#include#define r register
using std::string;
string goal[5]=,in[5];
int mx[8]=,sx;
int my[8]=,sy;
int t,dep;
inline int getdist(string a[5])
if(a[i][o]!=goal[i][o]) dist+=1;
} return dist;
}inline bool a_star(int s,int prex,int prey)
std::swap(in[sx3][sy3],in[sx2][sy2]);
if(a_star(s+1,sx3,sy3)) return 1;
std::swap(in[sx3][sy3],in[sx2][sy2]);
sx2-=mx[i],sy2-=my[i];
} return 0;
}signed main()
if(dep==16) printf("-1\n");
else printf("%d\n",dep);
}}
這裡的\(h(s)\)是八宮格內還缺幾個數就滿足題意
讀入比較噁心,要小心寫**
我這篇好像是luogu最優解
【**選注】
char map[8]=;
考慮到字典序的問題,我們列舉的時候1-8,最後來個對應
至於為啥不是i+'a'這種型別,為了保險(懶
int shrc[8]=,dep;
int shru[8]=,ans;
1-8所對應的狀態,為了好處理所以打亂順序,這相當於對應陣列
inline int getsituation()
獲得情況,看看最少還有幾個數沒有回到位置上
inline void change(char a[8],int rc,bool rule)
改動某一行rule取值意義
rc取值意義:
if(!st)
存在不需要搜尋或搜尋完畢的情況,此時記錄,退出
if(shrc[i]==prc&&shru[i]!=pru) continue;
防止出現兩次移動相當於沒移的情況
change(f[shrc[i]],shrc[i],!shru[i]);
相反方向回溯
#includeusing std::cin;
using std::cout;
char f[5][8],lu[100],map[8]=;
int shrc[8]=,dep;
int shru[8]=,ans;
inline int tmax(int a,int b,int c)
inline int getsituation();
a[f[1][3]-'0']+=1;a[f[1][4]-'0']+=1;a[f[1][5]-'0']+=1;
a[f[2][3]-'0']+=1;a[f[2][4]-'0']+=1;a[f[2][5]-'0']+=1;
a[f[3][4]-'0']+=1;a[f[4][4]-'0']+=1;
return 8-tmax(a[1],a[2],a[3]);
}inline void change(char a[8],int rc,bool rule)
else
switch(rc)
}inline bool a_star(int s,int prc,int pru)
if(s+st>dep) return 0;
for(int i=0;i<8;i++)
return 0;
}signed main(){
while(1){
cin>>f[1][1];if(f[1][1]=='0') break;
cin>>f[2][1]>>f[1][2]>>f[2][2];
for(int i=1;i<8;i++) cin>>f[3][i];
f[1][3]=f[3][3],f[2][3]=f[3][5];
cin>>f[1][4]>>f[2][4];
for(int i=1;i<8;i++) cin>>f[4][i];
f[1][5]=f[4][3],f[2][5]=f[4][5];
cin>>f[1][6]>>f[2][6]>>f[1][7]>>f[2][7];
dep=getsituation();ans=f[1][3]-'0';
while(!a_star(0,-1,-1)) dep+=1;
if(!dep) cout<
else for(int i=0;i容易發現,a*與ida*就是在原搜尋的基礎上加上幾行優化的東西,所以啟發式搜尋並沒有那麼難
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 它是利用問題擁有的啟發資訊來引導搜尋,達到減少搜尋範圍 降低問題複雜度的目的,這種利用啟發資訊的搜尋過程稱為啟發式搜尋。例題 八數碼問題 運用優先佇列,根據目前已經確定的位置算出目前的價值,並匯入...
啟發式搜尋
啟發式搜尋 啟發式搜尋就是在狀態空間中的搜尋對每乙個搜尋的位置進行評估,得到最好的位置,再從這個位置進行搜尋直到目標。這樣可以省略大量無謂的搜尋路徑,提高了效率。在啟發式搜尋中,對位置的估價是十分重要的。採用了不同的估價可以有不同的效果。在啟發式搜尋中,我們每次找到當前 最有希望是最短路徑 的狀態進...