例題:求馬的不同走法總數 問題描述:在一個4*5的棋盤上,馬的起始位置座標(縱,橫)位置由鍵盤輸入,求馬能返回初始位置的所有不同走法的總數(馬走過的位置不能重複,馬走“日”字)。
演算法分析: 由於棋盤的大小隻有4*5,所以只需使用回溯演算法,搜尋馬能返回初始位置的所有不同走法,效率基本上能達到要求。 遞迴的回溯演算法可描述為: procedure search(now:position); {now是當前位置} begin for 馬從當前位置now出發走一步到位置next的每一種走法 do begin if next在棋盤內 and next位置沒有走過 then if next=出發點 then 不同走法總數加1 else begin 標記next已經走過了; search(next); 取消位置next的標記; end; end; end; 下面討論演算法的具體實現。 棋盤用座標表示,點P(x,y)表示棋盤上任一個點,x,y的範圍是:1<=x<=4,1<=y<=5。
從P(x,y)出發,下一步最多有8個位置,記為P1,P2,„„,P8,若用k表示這8個方向,則k=1,2,„,8。即馬從P點出發,首先沿k=1的方向行進,當在此方向走完所有的不同走法後,就進行回溯,改變k=2方向繼續行進„„
各點座標的計算。設P點座標為(x,y),則能到達點的座標分別為P1(x+1,y-2),P2(x+2,y-1),„,P7(x-2,y-1),P8(x-1,y-2)。為簡化座標的計算,引入增量數組:
direction:array[1..8] of position=
((x:1;y:-2),(x:2;y:-1),(x:2;y:1),(x:1;y:2),
(x:-1;y:2),(x:-2;y:1),(x:-2;y:-1),(x:-1;y:-2));
則按方向k能到達點的座標是: Pk(x+direction[k].x,y+direction[k].y)。 程式如下:
#include <cstdlib>
#include <iostream>
using namespace std;
#define row 4
#define line 5
struct position
{
int x,y;
};
const position direction[8]=
{(1,-2),(2,-1),(2,1),(1,2),(-1,2),(-2,1),(-2,-1),(-1,-2)};
int pass[4][5];
position start;
int total;
void search(position now)
{
int i;
position next;
for (i=0;i<8;i++)
{
next.x=now.x+direction[i].x;
next.y=now.y+direction[i].y;
if ((next.x>=0)&&(next.x<=row-1)&&(next.y>=0)&&(next.y<=line-1)&&(pass[next.x][next.y])==0)
if((next.x==start.x)&&(next.y==start.y))
total++;
else
{
pass[next.x][next.y]=1;
search(next);
pass[next.x][next.y]=0;
}
}
}
int main(int argc, char *argv[])
{
total=0;
for(int i=0;i<row;i++)
for(int j=0;j<line;j++)
{
pass[i][j]=0;
}
cout<<"輸入開始位置"<<endl;
cin>>start.x>>start.y;
search(start);
cout<<"TOTAL="<<total<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}