1. 程式人生 > >馬走日(深搜 C++)

馬走日(深搜 C++)

馬走日
總時間限制: 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; //結束整個程式 }