八數碼問題
【題意】
編好為1~8的8個正方形滑塊擺成3行3列(一個格子為空),如圖所示
每次可以移動空格相鄰的滑塊到空格,要計算出能移動出目標局面的最小步數,如無法達到則輸出-1。
【分析】
我們可以把每一種局面定義為一種“狀態”,而每個狀態就是由9個格子的編號依次排列組成,如上圖左的狀態為:1,5,2,4,3,0,7,8,6,同理右的狀態為:1,2,3,4,5,6,7,8,0。然後我們可以用寬度優先遍歷搜索(BFS)的方法,對每一種狀態都進行擴展出新的狀態,然後知道搜索出目標狀態為止。
【代碼】
typedef int State[9]; //定義“狀態”類型
const int Maxstate = 1000000;
State st[Maxstate],goal; //狀態數組
int dist[Maxstate];
//如果要打印方案,還要定義一個父親編號數組 int fa[Maxstate];
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
void init(){} //初始化函數
int bfs()
{
init();
int front=1;
int rear=2;
while(front<rear)
{
State& s = st[front];
if(memcmp(goal,s,sizeof(s))==0) return front;
int z;
for(z=0;z<9;z++) if(!s[z]) break;
int x=z/3,y=z%3;
for (int d=0;d<4;d++)
{
int newx=x+dx[d];
int newy=y+dy[d];
int newz=newx*3+newy;
if(newx>=0 && newx<3 && newy>=0 &&newy<3)
{
State& t=st[rear];
memcpy(&t,&s,sizeof(s));
t[newz]=s[z];
t[z]=s[newz];
dist[rear]=dist[front]+1;
if(insert(rear)) rear++; //判重
}
}
front++;
}
return 0;
}
上面這段代碼缺少一個main()函數,一個init()函數和一個判重的insert()函數,我覺著比較重要的一個點時定義“狀態”類型的寫法,我開始覺著應該是typedef int[9] State這麼寫的,但是不對,具體為什麼要那麼寫我也不清楚,反正很容易寫錯。然後就是最關鍵的bfs函數中用了很多“引用”,這可以學習一下,這樣做很方便,比指針好理解。