暴搜+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 ...