馬走日(深搜 C++)
阿新 • • 發佈:2019-02-20
馬走日
總時間限制: 1000ms 記憶體限制: 1024kB
描述
馬在中國象棋以日字形規則移動。
請編寫一段程式,給定n*m大小的棋盤,以及馬的初始位置(x,y),要求不能重複經過棋盤上的同一個點,計算馬可以有多少途徑遍歷棋盤上的所有點。
輸入
第一行為整數T(T < 10),表示測試資料組數。
每一組測試資料包含一行,為四個整數,分別為棋盤的大小以及初始位置座標n,m,x,y。(0<=x<=n-1,0<=y<=m-1, m < 10, n < 10)
輸出
每組測試資料包含一行,為一個整數,表示馬能遍歷棋盤的途徑總數,0為無法遍歷一次。
樣例輸入
1
5 4 0 0
樣例輸出
32
思路點拔:標準深搜,就是將起點作為搜尋的起點,然後列舉馬的八個走向,由於不是每個馬都有八個走向,所以我們每走一步就要判斷有沒有越界,如果沒有,就將當前點做為新的起點,然後繼續遞迴走下一步,並把走過的地方標記為1,知道走到無路可走是,就結束遞迴,方案數加1,然後將棋盤重新清空,列舉下一種情況,直到沒有其他的情況,整個dfs就結束了,聽起來有點抽象,上程式碼吧~
#include<iostream> //建議不要用bits萬能標頭檔案
#include<cstdio>
#include<cstring>
using namespace std;
int f[21][22],n,m,t; //f陣列記錄點有沒有走過
int x[10]={-2,-2,-1,1,2,2,1,-1},y[10]={-1,1,2,2,1,-1,-2,-2};//八個方向
int x1,y1,ans;
void dfs(int a,int b) //搜尋過程
{
bool p=true; //標記,判斷馬是否可以遍歷整個棋盤
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(f[i][j]==0) //如果該點走過
{
p=false; //標記為錯誤
break; //結束內層迴圈
}
}
}
if(p==true) //如果可以遍歷整個棋盤,就將方法數加1
{
ans++;
return; //不用在搜下去了
}
for(int i=0;i<=7;i++) //列舉馬走的8個方向
{
int l=a+x[i];
int k=b+y[i];
if(f[l][k]==1) //如果該點曾經走過,就結束當此迴圈
continue;
if(l>0&&l<=n&&k>0&&k<=m) //判斷是否越界
{
f[l][k]=1; //將該點標記為1,表示不能走了
dfs(l,k); //將當前座標作為新的起點,繼續遞迴馬要走的下一步
f[l][k]=0; //回溯
}
}
}
int main()
{
scanf("%d",&t); //輸入有多少組測試資料
for(int i=1;i<=t;i++)
{
scanf("%d %d %d %d",&n,&m,&x1,&y1); //輸入其實座標與終點座標
x1++;
y1++;
memset(f,0,sizeof(f)); //將f陣列清空
f[x1][y1]=1; //起點不能再走
ans=0; //方案數清0
dfs(x1,y1);//開始搜尋,將起點的座標作為第一個搜尋的
printf("%d\n",ans); //輸出方案數
}
return 0; //結束整個程式
}