通過這個題,學習了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...