八數碼總結

2022-05-28 01:45:10 字數 4627 閱讀 8897

暴搜+queue,如果空格用』0』表示的話可以直接將狀態壓縮成乙個9位整數,也可以用字串表示狀態,用結構體表示狀態+步數+空格的位置。

/*

264137058

815736402

*/#include

#include

#include

#include

#include

using

namespace

std;

mapvis;

int m, n;

struct state;

state s;

string goal;

int dx[4] = ;

int dy[4] = ;

int bfs()

); }}}

return -1;

}int main (void)

s = (state);

int res = bfs();

if(res == -1) cout

<<"no solution"

cout

《模擬佇列+康拓展開/雜湊/stl set判重,學習紫書上的**~

注意其中康拓展開

康拓展開#include

#include

#include

#include

using

namespace

std;

typedef

int state[9];//表示state 代表 int[9]

const

int maxn = 1e7 + 5;

state st[maxn], sta, goal;

int dist[maxn];

int dx[4] = ;

int dy[4] = ;

/*2 6 4 1 3 7 0 5 8

8 1 5 7 3 6 4 0 2

*//******把0~8的全排列和0~362879的整數一一對應起來****/

int vis[400000], fact[10];

void init()

int insert(int s)

if(vis[code]) return

0; return vis[code] = 1;

}int bfs()

}fro++;

}return -1;

}int main (void)

雜湊:
const

int hashsize = 1000003;//大質數

int head[hashsize], next[hashsize];

void init()

int hash(int s)

int insert(int s)

next[s] = head[h];

head[h] = s;

return

1;}

set判重:
set

vis;

void init()

int insert(int s)

模擬佇列+雙向bfs~~這裡判重隨便選乙個就好啦~~節約一半的時間和一半的空間,真心快多了~

#include

#include

#include

using

namespace

std;

typedef

int state[9];

const

int maxn = 1e7 + 5;

state st[maxn];

int dx[4] = ;

int dy[4] = ;

int fact[maxn], vis[maxn], dist[3][maxn];

/*2 6 4 1 3 7 0 5 8

8 1 5 7 3 6 4 0 2

*/void init()

int canto(state s)

code += fact[8 - i] * cnt;

}return code;

}int bfs()

else

if(vis[ct] != vis[cs])}}

fro++;

}return -1;

}int main (void)

a* + 優先順序佇列(小頂堆)+ 曼哈頓距離

a*搜尋演算法

當任何第二次走到乙個點的時候,判斷最小步驟是否小於記錄的內容,如果是,則更新掉原最小步數,關於記錄最小步數,如果使用曼哈頓距離作為h(

n),則不必記錄,這時的a*滿足:每個點第一次被選出搜尋佇列時的狀態為到達此點的最優解,而且每個點只會進入佇列一次。所以只需要設定乙個vis的陣列就夠了。

#include

#include

#include

#include

/*1 2 3 4 5 6 7 8 0

1 2 3 4 5 6 0 7 8

2 6 4 1 3 7 0 5 8

8 1 5 7 3 6 4 0 2

*/using

namespace

std;

struct state

};const

int maxn = 1e7 + 5;

state sta, goal;

int dx[4] = ;

int dy[4] = ;

int fact[maxn], vis[maxn];

void init()

int canto(state s)

code += fact[8 - i] * cnt;

}return code;

}int geth(state be)

}return res;

}int astar()}}

return -1;

}void print (state t)

}sta.g = 0;

sta.can = canto(sta);

//print(sta);

for(int i = 0; i < 9; i++) cin>>goal.a[i];

goal.can = canto(goal);

//print(goal);

int res = astar();

if(res != -1) cout

cout

<<"no solution"

0;}

ida* + 曼哈頓距離

ida*即迭代加深的a*搜尋,實現**是最簡練的,無須狀態判重,無需估價排序。那麼就用不到雜湊表,堆上也不必應用,空間需求變的超級少。效率上,應用了曼哈頓距離。同時可以根據深度和h值,在找最優解的時候,對超過目前最優解的地方進行剪枝,這可以導致搜尋深度的急劇減少,所以,這是乙個致命的剪枝!因此,ida*大部分時候比a*還要快,可以說是a*的乙個優化版本!

#include

#include

#include

#include

using

namespace

std;

const

int maxn = 1e7 + 5;

int maxdepth;

int dx[4] = ;

int dy[4] = ;

/*1 2 3 4 5 6 7 8 0

1 2 3 4 5 6 0 7 8

2 6 4 1 3 7 0 5 8

8 1 5 7 3 6 4 0 2

*/struct state

;state st[maxn];

state goal, sta;

int geth(state be)}}

return res;

}void print(state s)

}return0;}

int idastar()

return maxdepth;

}int main (void)

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

int res = idastar();

if(res < 100) cout

cout

<<"no solution"

0;}

有關逆序數

空格在同一行上進行移動,1~8的排列逆序數不變,空格在同一列上進行移動,1~8的排列逆序數發生變化的對數為偶數。所以初始狀態的逆序數與目標態同奇偶則有解,反之無解;

這一優化可以用在上面的所有方法中,也是乙個很重要的剪枝。

int reverse(state

s) }

return cnt % 2;

}

真的是細節決定一切。。。竟然寫了一天。。。一半時間還都用來除錯。。。寫的時候就應該心思細膩,檢查的時候模擬一遍過程,任何細節都不能放過!

八數碼問題

八數碼問題 一.八數碼問題 八數碼問題也稱為九宮問題。在3 3的棋盤,擺有八個棋子,每個棋子上標有1至8的某一數字,不同棋子上標的數字不相同。棋盤上還有乙個空格,與空格相鄰的棋子可以移到空格中。要求解決的問題是 給出乙個初始狀態和乙個目標狀態,找出一種從初始轉變成目標狀態的移動棋子步數最少的移動步驟...

八數碼問題

2 6 4 1 3 7 0 5 8 8 1 5 7 3 6 4 0 2 樣例輸出 還有就是重判的問題,如何重判呢?第一種方法 把排列變成整數,然後只開乙個一維陣列,也就是說設計一套排列的編碼和解碼函式,把0 8的全排列和0 362879的整數意義一一對應起來。時間效率高,但編碼解碼法適用範圍並不大,...

八數碼問題

八數碼問題 題意 編號為1 8的8個正方形滑塊被擺成3行3列 有乙個格仔留空 如下圖所示 每次可以把與空格相鄰的滑塊 有公共邊才算相鄰 移到空格中,而他原來的位置 就成為了新的空格。如果無法到達目標局面,則輸出 1。2 6 4 13 75 8 移到後 8 1 5 73 642 樣例輸入 2 6 4 ...