演算法入門經典第二版第七章八數碼問題

2021-07-24 06:29:57 字數 2777 閱讀 3931

通過這個題,學習了bfs不用stl的實現方式,模擬佇列。

學會了用一維陣列,存圖狀態的姿勢。

複習了記錄路徑,學習了hash的應用。。

題目要求,給出八數碼初始狀態,目標狀態,問最少移動幾步可以達到目標狀態。

樣例輸入:

2 6 4 1 3 7 0 5 8

8 1 5 7 3 6 4 0 2

樣例輸出:

31lrj使用一維陣列儲存圖的狀態,然後使用bfs,列舉所有可能的移動(對於空格當前的位置,可以移動的方向)。

然後在每次佇列中彈出隊首狀態時,和目標狀態比較。

難點在於對當前狀態的標記,lrj介紹了3種方法,這裡只說一下前兩種。

注意這裡的每個節點的狀態,是乙個9位的一維陣列。我們可以把它轉化成9位十進位制數,像這樣。

int v = 0;

for(int i = 0; i < 9; i++) v = v * 10 + s[i];

但是如果我們要開乙個9位數字大小的陣列,那是開不了的。

於是出現了第一種方法。使用set標記,這是一種很常見的標記大數的方法。

setvis;

void init_lookup_table1()

int try_to_insert1(int s)

但是set的訪問效率是o(log(n)),比起直接用陣列(如果可能的話)(o(1))要慢得多。

於是出現了第二種,lrj說競賽中常用的方法--hash。

這裡的maxhashsize只開了比maxstate大3的大小,可以根據記憶體大小自行定義。

然後使用了簡單的mod操作進行hash,最簡單的hash函式了。

對於對映到同乙個位置的數,使用鍊錶將數存起來進行判斷。(當然可能出現很長的鍊錶,效率就低了,需要合理的hash函式來做)

很明顯,這裡把要開的陣列 1e9的陣列,縮小到1e6+3,陣列就能開下了。

// hash

const int maxhashsize = 1000003;

int head[maxhashsize], next[maxstate];

void init_lookup_table2()

int hash(state& s)

int try_to_insert2(int s)

next[s] = head[h]; //往頭前插入。

head[h] = s; //頭結點置為s

return 1;

}

最後一種方法,設計排列的編碼和解碼函式,把0~8的全排列和0~362879的整數一一對應起來,這個博主也沒有深入研究,直接貼**了。

int vis[362880], fact[9];

void init_lookup_table()

int try_to_insert(int s)

if(vis[code]) return 0;

return vis[code] = 1;

}

最後貼出前兩個的原始碼,附帶了列印路徑的**。

// 八數碼

// winjourn

#include#include#include#includeusing namespace std;

typedef int state[9];

const int maxstate = 1000000;

state st[maxstate], goal;

int dist[maxstate];

int fa[maxstate];

setvis;

void init_lookup_table1()

int try_to_insert1(int s)

// hash

const int maxhashsize = 1000003;

int head[maxhashsize], next[maxstate];

void init_lookup_table2()

int hash(state& s)

int try_to_insert2(int s)

next[s] = head[h]; //往頭前插入。

head[h] = s; //頭結點置為s

return 1;

}const int dx = ;

const int dy = ;

int bfs()

}front++;

} return 0;

}int main() {

for(int i = 0; i < 9; i++)

scanf("%d", &st[1][i]);

for(int i = 0; i < 9; i++)

scanf("%d", &goal[i]);

int ans = bfs();

if(ans > 0) printf("%d\n", dist[ans]);

else printf("-1\n");

int head = ans;

while(head != -1){

for(int i = 0; i < 9; i++){

cout<

C 入門經典 第七章

本章內容 執行程式的兩種方式 除錯模式和非除錯模式。輸出視窗 包括輸出和除錯兩種模式。1.輸出除錯資訊 debug.writeline 僅在除錯模式下執行 trace.writeline 還可用於發布程式 using system using system.collections.generic u...

演算法入門經典 第七章 例題7 2 八皇后問題

原本利用回溯思想解決的經典八皇后問題,其實也是可以用遞迴解決的 八皇后的遞迴解決思路 從第一行開始,依次判斷0 8列的哪一列可以放置queen,這樣就確定了該行的queen的位置,然後行數遞增,繼而遞迴實現下一行的判斷,依次類推直到行數增加到8 行數從0開始的 此時為遞迴 歸的條件,即表示一種八皇后...

CSAPP第七章家庭作業(原書第二版)

7.6 buf前加了extern是外部符號,由main.c定義,故定義符號的模組是main.o,是int型變數,屬於.data節 bufp0和swap函式前未加extern和static,故是全域性符號,都在swap.c中定義,故定義符號的模組是swap.o,變數bufp0屬於.data節,swap...