題意:3×3九宮棋盤,放置數碼為1 -8的8個棋牌,剩下乙個空格,只能通過棋牌向空格的移動來改變棋盤的布局。給出初始布局和目標布局,問最少多少步移動能夠使初始布局變為目標布局
分析:題目思路很清晰,直接廣搜即可。但是問題是如何儲存狀態並且判重?我們對於每乙個狀態進行觀察,均是由0-8構成的乙個全排列,那麼狀態一共有9!=362880種,那麼我們有多種方案進行儲存,在這裡我們只討論兩種
- 方案一:直接用乙個九位數(或者陣列)儲存
- 方案二:將其對映到1~9!的編碼中
我們可以將兩種方法結合起來使用,用方案一來進行儲存狀態,用方案二來進行判重。方案一比較簡單,方案二的實現具體有兩種選擇:
1.使用取餘法放入雜湊表,在這裡使用拉鍊法或者是線性探查法或者雙函式法等等等等都是可行的
2.利用此九位數可以轉換成1~9全排列(每個加1)的性質,將它描述為a1
a2a3
...a
9 ,對於每乙個ai
都指定乙個bi
表示在ai
前面比ai
小的數的個數,那麼對於這個排列,它的編號就是∑9
i=1(
ai−b
i−1)
∗(9−
i)! ,這個編號的範圍是0~9!-1,若要生成平時1~9!的編號,加1就可以了,那麼我們就可以開乙個1..362880的布林陣列來進行判重操作了
經過分析我們發現,第一種實現方案有衝突,但是雜湊函式簡單有效,判重操作較為簡單;第二種實現方案完全避免了衝突,但是算出全排列編碼的函式耗時較多,大家可以根據實際情況自由的選擇
詳細**如下:
//全排列版
#include
using
namespace
std;
typedef pair doub;
int target=46685,num[10],number[10],w,sum,h,temp;
bool vis[400000];
queue
q;int g(int x)
return ans;
} int hash()
ans+=(num[i]-number[num[i]]-1)*g(9-i);
}return ans;
}void work1(int now)
return ;
}int work2()
return ans;
}int main() );
while(!q.empty())
if(w%3!=1) );
}temp=num[w];num[w]=num[w-1];num[w-1]=temp;
}if(w-3>0) );
}temp=num[w];num[w]=num[w-3];num[w-3]=temp;
}if(w%3!=0) );
}temp=num[w];num[w]=num[w+1];num[w+1]=temp;
}if(w+3
<10) );
}temp=num[w];num[w]=num[w+3];num[w+3]=temp;}}
}
by:chlience 題解 八數碼問題
八數碼問題描述 八方塊移動遊戲要求從乙個含 8 個數字 用 1 8 表示 的方塊以及乙個空格方塊 用 0 表示 的 3 3 矩陣的起始狀態開始,不斷移動該空格方塊以使其和相鄰的方塊互換,直至達到所定義的目標狀態。空格方塊在中間位置時有上 下 左 右 4 個方向可移動,在四個角落上有 2個方向可移動,...
搜尋 八數碼問題
搜尋 高階列舉 有順序有策略地列舉狀態空間中的節點,尋找問題 的解 狀態空間 由所有狀態構成的狀態樹 經典八數碼問題 有乙個3 3的棋盤,其中有0 8共9個數字,0表示空 格,其他的數字可以和0交換位置。求由初始狀態 到達目標狀態的步數最少的解?8 2 3 1 4 6 5 7 0 1 2 3 4 5...
A 搜尋 八數碼問題
八數碼問題,簡單地來描述是這樣的 在乙個九宮格內,填有1 2 3 4 5 6 7 8,八個阿拉伯數字,有乙個格仔為空白。就下面這樣,這是乙個沒有歸位的九宮格。12 3784 65 未歸位的九宮格 對於上面這個九宮格,我們要通過移動數字來使之歸位,每次移動都只能是與空白格相鄰的數字移到空白格裡面。最終...