从(0,0)到(n,n)——广度优先及其改进
最近力扣刷了一些廣度優先,深度優先的題目,看了b站的奇樂編程學院的一個尋路算法視頻,突然想到這個知識點在離散的課堂上也講過,從(0,0)到(n,n)要走多少步,其中還包括一些特殊問題,比如不能通過對角線,有障礙物等。
卡特蘭數
學過離散的孩子應該都知道這個神奇的東西,我理解的卡特蘭數是一個滿足很多現實情況的數列。比如一個棧(無窮大)的進棧序列為1,2,3,…,n,有多少個不同的出棧序列? 又比如依據乘法結合律,不改變其順序,只用括號表示成對的乘積,試問有幾種括號化的方案?…比較經典的問題就是今天要討論的從(0,0)到(n,n)一共有多少種方式或者是最短路徑是什么。卡特蘭數是有公式可以解決的,這里先給出求卡特蘭數c++的應用。
void catalan() //求卡特蘭數 {int i, j, len, carry, temp;a[1][0] = b[1] = 1;len = 1;for(i = 2; i <= 100; i++){for(j = 0; j < len; j++) //乘法a[i][j] = a[i-1][j]*(4*(i-1)+2);carry = 0;for(j = 0; j < len; j++) //處理相乘結果{temp = a[i][j] + carry;a[i][j] = temp % 10;carry = temp / 10;}while(carry) //進位處理{a[i][len++] = carry % 10;carry /= 10;}carry = 0;for(j = len-1; j >= 0; j--) //除法{temp = carry*10 + a[i][j];a[i][j] = temp/(i+1);carry = temp%(i+1);}while(!a[i][len-1]) //高位零處理len --;b[i] = len;} }廣度優先
廣度優先大家都很熟了,而且尋道這類問題廣度優先幾乎是萬能解法,當然了既然是萬能解法那往往效率就不是最高的。從起點開始把起點周圍四個點進隊,每次從隊首拿一個出來并標記為已訪問,直到隊列為空則跳出循環。
#include<iostream> #include<stdio.h> #include<vector> #include<map> #include<queue> #include<stack> using namespace std;const int Min = 0; const int Max = 10; int Map[Max + 1][Max + 1] = { 0 }; int mark[Max + 1][Max + 1] = { 0 }; class find_path { public:void dfs(pair<int,int> begin,pair<int,int>end) {//Exception//...queue<pair<int, int>>qu;qu.emplace(begin);while (!qu.empty()) {pair<int, int>temp = qu.front();qu.pop();if (temp.first-1 >= Min && !Map[temp.first-1][temp.second ]) {pair<int, int>up(temp.first-1, temp.second );if (up == end)break;qu.emplace(up);Map[temp.first-1][temp.second ] = 1;mark[temp.first-1][temp.second ] = 1;}if (temp.first+1 <=Max && !Map[temp.first+1][temp.second ]) {pair<int, int>down(temp.first+1, temp.second );if (down == end)break;qu.emplace(down);Map[temp.first+1][temp.second ] = 1;mark[temp.first+1][temp.second ] = 2;}if (temp.second-1 >= Min && !Map[temp.first ][temp.second-1]) {pair<int, int>left(temp.first , temp.second-1);if (left == end)break;qu.emplace(left);Map[temp.first][temp.second-1] = 1;mark[temp.first][temp.second-1] = 3;}if (temp.second + 1 >= Min && !Map[temp.first][temp.second + 1]) {pair<int, int>right(temp.first , temp.second+1);if (right == end)break;qu.emplace(right);Map[temp.first][temp.second + 1] = 1;mark[temp.first][temp.second + 1] = 4;}}} };int main() {find_path test;pair<int, int>begin(1, 1);pair<int, int>end(6, 6);Map[begin.first][begin.second] = 1;mark[begin.first][begin.second] = 5;mark[end.first][end.second] = 6;test.dfs(begin,end);for (int i = 0; i < Max + 1; i++) {for (int j = 0; j < Max + 1; j++) {switch (mark[i][j]) {case 1:cout << "↑ "; break;case 2:cout << "↓ "; break;case 3:cout << "← "; break;case 4:cout << "→ "; break;case 5:cout << "起 "; break;case 6:cout << "終 "; break;}}cout << endl;}}寫的確實有點啰嗦了,四個if直接暴露了我編程新手的現實。這里沒有增加障礙物,當然也并不麻煩,只需要提前把障礙物的點的map設為1即可。
A star 算法
這是在視頻里面看到的,據視頻所說這是最常見的算法,它比廣度優先高級的地方在于增加了一個花費(感覺有點像貪心算法)把當前花費加上預估花費作為判斷隊列出隊的條件,花費少的先出隊。這可以幫助我們盡快找到最短路徑。其實也就是把廣度優先算法中的隊列換成優先隊列即可,代碼以后再補充吧。
這里貼出視頻網址https://www.bilibili.com/video/BV1bv411y79P。
總結
以上是生活随笔為你收集整理的从(0,0)到(n,n)——广度优先及其改进的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国电信实习
- 下一篇: union一个有趣的应用