8數碼問題的廣搜在網上可以找到**,廣搜一般可以找到最優解,但是深搜不一定能找到最優解。一般的深搜多是指定最大遞迴深度的深搜,一般情況下,問題解的深度很難確定。因此深蒐會出現三種情況,一是找到最優解,二是在迭代深度內找不到解,三是找到解但不是最優解。第一種情況自然是最好的,不過較經常出現的是第三種,在指定迭代深度不適當的時候也會出現第二種情況。
在迭代深度內找不到解是最糟糕的一種情況,對這個問題沒有什麼好的解決辦法。有時候我們可以用試湊法,多次測試來找到乙個比較好的遞迴深度。對同一輸入在不同迭代深度範圍內的比較如下:
輸入資料
6 2 8
0 1 4
7 3 5
對於上面的測試資料,廣搜的搜尋深度為17,是最優的結果。下面的**中列出了深搜的搜尋深度,可以看到深搜的搜尋深度不是固定的。
最大深度
1720
30100
求得解時深度
1719
2997
在下面給出的8數碼問題的深度求解演算法中,採用非遞迴的深度優先搜尋,並且給出了乙個較合理的遞迴深度。對於**中的hash值得求取,可能有好些朋友看不大懂,這裡我簡單講解一些為什麼這樣計算hash值。
我們設 hash = a * 8! + b * 7! + c * 6! + d * 5! + e * 4! + f * 3! + g * 2! + h * 1! + i * 0! , 其中 a - i 分別是 0 - 8 的逆序數。到了這裡,知道逆序數的朋友可以一下子就明白了。我們可以很容易的證明 a <= 8 , b < 8 , c < 7 ...... b < 8 則一定有 b * 7! < 8! 我們可以得到,如果 hash > 8! ( 即 (hash / 8! ) != 0 ) 則一定有 a != 0 ,且 hash / 8! = a,依次類推,我們可以證明 (hash % 8! ) / 7! = b ......這就是乙個對映的過程,這個對映可以保證對於一組(a , b , c , d , e , f , g , h , i )一定有唯一的 hash 並且對於 乙個 hash 一定有唯一的一組( a , b , c , d , e , f , h , i )相對應。
【edigital.h】
#pragma once
#include using std::queue;
#define hashtablesize 362881
#define digitalsize 9
#define maxdeepth 30 //深度優先搜尋的最大搜尋深度,對有些資料,其最優解可能超過30深度,這時候深搜,程式將不會給出正確結果
class edigital
detail;
private:
typedef struct maps
map, *pmap;
enum direction
;public:
edigital(const int a[ digitalsize ]);
edigital(const detail& detail);
~edigital(){}
public:
queuefindpath();
void bfs();
void dfs ( int depth = maxdeepth);
private:
inline int hashvalue(map& parent , int direct );
void init(const detail& detail);
private:
int endindex;
map org;
static const int factorial[ digitalsize ];//; //8!,7!,6!,5!,4!,3!,2!,1!,0!
static const int derection[ 4 ];// ;// 可移動的四個方向,向上下移動空格(0)位置變化3,左右移動變化1
static int hashtable[ hashtablesize ];//
};
【editital.cpp】#include "edigital.h"
#include#include#includeconst int edigital::factorial[ 9 ] = ; //8!,7!,6!,5!,4!,3!,2!,1!,0!
const int edigital::derection[ 4 ] = ;// 可移動的四個方向,向上下移動空格(0)位置變化3,左右移動變化1
int edigital::hashtable[hashtablesize] = ;
edigital::edigital(const int a[ digitalsize ])
org.index = index + 1 ;
endindex = sum%2 ? 161328:322561; // 目標狀態的hash值,八數碼存在無解的情況 123456780的hash值為322561
}/**
*hash值的計算
*parent:父狀態的hash值
*direct:移動的方向
**/inline int edigital::hashvalue(map& parent , int direct )
case down :
case left : return newindex - 40320; break;
case right : return newindex + 40320; break;
} return newindex;
}/**
** 廣度優先搜尋
***/
void edigital::bfs() }
return ;
}/**
** 深度優先搜尋
***/
void edigital::dfs( int depth /*= maxdeepth*/)
else//擴充套件
}if(stack.empty())
hashtable[ endindex ] = -1;
return ;
}/**
** 通過hash表中記錄的進行查詢路徑
***/
queueedigital::findpath()
int nixu[9];
detail temp;
queueresult;
while( ! stack.empty())
memset( temp.a , -1 , digitalsize *sizeof(int));
for( int i = 0 ; i < 9 ; ++ i ) // 根據逆序計算排列
temp.a[j] = i ;
} result.push(temp);
} return result ;
}
【main.cpp】
#include#include"edigital.h"
#include#include#includeusing std::cout;
using std::cin;
using std::endl;
using std::string;
using std::queue;
int main()
else
eight.bfs();
cout << "計算用時:" << gettickcount()-time << "ms\n";
queuedetails = eight.findpath();
printf("共需: %d 步\n",details.size()-1);
getchar();
int count=0;
while( ! details.empty())
if(0 != details.size() )
}return 0;
}
廣搜和深搜
一般來說,廣搜常用於找單一的最短路線,或者是規模小的路徑搜尋,它的特點是 搜到就是最優解 而深搜用於找多個解或者是 步數 已知 好比3步就必需達到前提 的標題,它的空間效率高,然則找到的不必定是最優解,必需記實並完成全數搜尋,故一般情況下,深搜需要很是高效的剪枝 優化 像搜尋最短路徑這些的很顯著若是...
搜尋(深搜 廣搜)
我記得在遙遠的2017年,我會敲的搜尋也只有暴力列舉了。那個時候的我深搜剛會一丟丟,所以也只配切切水題,然而經常死迴圈re那是肯定的。如今的我因為在多次比賽中都死於搜尋,那就必須得認真磕一下了。其實是這樣的 我眼裡認為的暴力就真的只是暴力,暴力無非就兩種 列舉打表和模擬。然而在這麼多次比賽後,我總能...
深搜和廣搜
深度優先搜尋屬於圖演算法的一種,英文縮寫為dfs即depth first search.其過程簡要來說是對每乙個可能的分支路徑深入到不能再深入為止,而且每個節點只能訪問一次 採用的搜尋方法的特點是盡可能先對縱深方向進行搜尋。基本思路 深度優先遍歷圖的方法是,從圖中某頂點v出發 1 訪問頂點v 2 依...