8數碼問題 深搜 廣搜

2021-06-22 03:27:16 字數 4001 閱讀 9069

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 依...