這是一種很奇特的演算法。。
當然理解了以後就不那麼奇特了。。
直接看題:
在3×3
的棋盤上,擺有八個棋子,每個棋子上標有1至
8的某一數字。棋盤中留有乙個空格,空格用
0來表示。空格周圍的棋子可以移到空格中。要求解的問題是:給出一種初始布局(初始狀態)和目標布局(為了使題目簡單
,設目標狀態為
123804765
),找到一種最少步驟的移動方法,實現從初始布局到目標布局的轉變。
樣例輸入:
283104765
友情樣例輸入圖:
樣例輸出: 4
愛心樣例解釋: 把
8下移一位,再將
2右移一位,將
1上移一位,最後將
8左移一位。
思考:1.可以用
bfs實現嗎 2.
可以直接
dfs嗎
顯然不可以。。
為什麼呢?
先思考dfs:
dfs有一些很重要的東西。第一是邊界,其次是一些剪枝之類的。很顯然,這道題你不知道移動幾步才能到達目標狀態,也就是你無法定出乙個邊界,讓你的程式停下來。
再思考bfs:
每一層都有四種選擇,對應四種狀態。不斷擴充套件,直到有一種與目標狀態相等,就結束,看似很完美的實現了。但我們深入思考一下,
你如何儲存每一種狀態,明顯無法儲存。
針對這種沒有邊界又不好儲存狀態的搜尋題,就出現了迭代加深
(假定乙個邊界,進行搜尋,若達到要求,就停止,否則將邊界擴充套件一層,再次搜尋)
其實和dfs
相比就多了一句話,下面給出**:
#include#pragma g++ optimize(2)
usingnamespacestd;
#define fz(i,j,k) b[i][j]=int(s[k]-'0')
strings;
int k,l,r;
int a[4][4]=//目標狀態,b[4][4]={};
bool bd()//判斷與目標狀態是否相等
return1;}
bool find(int x,int y,int s,int p)//x,y是0所在的座標,s為移動步數,p是乙個剪枝思想,用來記錄上一層移動的方向,如果這一層往回走,顯然不是最優的。
if(s==k)return0;
if(x>1&&p!=1)
b[x-1][y]=b[x][y];
b[x][y]=0;
}if(x<3&&p!=2)
b[x+1][y]=b[x][y];
b[x][y]=0;
}if(y>1&&p!=3)
b[x][y-1]=b[x][y];
b[x][y]=0;
}if(y<3&&p!=4)
b[x][y+1]=b[x][y];
b[x][y]=0;
}return0;}
int main()
{ cin>>s;
int p=0;
for(int i=0;i
C 實現八數碼的IDEA 迭代加深A 演算法
八數碼是乙個經典的人工智慧難題,因為好的演算法在八數碼問題中將搜尋的幾種經典方法體現的淋漓盡致,經過幾種演算法的比較,我發現用迭帶加深的啟發示演算法的效率最好,而且求得解為最優解.開始實現時老是在查詢cloesd表時耗費時間,因此好多case都要算很長時間,最長竟達30分鐘,後來將cloesd儲存在...
八數碼問題
八數碼問題 一.八數碼問題 八數碼問題也稱為九宮問題。在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的整數意義一一對應起來。時間效率高,但編碼解碼法適用範圍並不大,...