马走日模型出现在DFS和数学推导两大方向:

可根据数据范围快速区分,数据范围极小时可想到用dfs暴搜;若数据过大导致DFS爆掉,故可通过模拟找到数学规律,分类求解(牛客)。

【acwing1116】马走日_ios

dfs跳出条件!:遍历过所有点

法一:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 20;
int t, n, m; 
int ans;//答案(全局变量统计方案数)
int g[N][N];
int dx[8] = {1,2,2,1,-1,-2,-2,-1};
int dy[8] = {2,1,-1,-2,-2,-1,1,2};
void dfs(int x, int y, int cnt){
	if(cnt == n*m){//搜遍所有点 
		ans ++ ;
		return;
	}
	g[x][y] = 1;
	for(int i = 0; i<8; i++){
		int a = x+dx[i], b = y+dy[i];
		if(a<0 || a>=n || b<0 || b>=m) continue;
		if(g[a][b]) continue;
		dfs(a, b, cnt+1);
	}
	g[x][y] = 0;
}
int main(){
	cin>>t;
	while(t--){
		int x, y;
		cin>>n>>m>>x>>y;
		ans = 0; 
		memset(g, 0, sizeof g);
		dfs(x, y, 1);
		cout<<ans<<endl;
	}
	return 0;
}

法二:更改、恢复现场的位置略有不同(个人比较习惯)

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 20;
int t, n, m; 
int ans;//答案(全局变量统计方案数)
int g[N][N];
int dx[8] = {1,2,2,1,-1,-2,-2,-1};
int dy[8] = {2,1,-1,-2,-2,-1,1,2};
void dfs(int x, int y, int cnt){
	if(cnt == n*m){//搜遍所有点 
		ans ++ ;
		return;
	}
	for(int i = 0; i<8; i++){
		int a = x+dx[i], b = y+dy[i];
		if(a<0 || a>=n || b<0 || b>=m) continue;
		if(g[a][b]) continue;
		g[a][b] = 1;
		dfs(a, b, cnt+1);
		g[a][b] = 0;
	}
}
int main(){
	cin>>t;
	while(t--){
		int x, y;
		cin>>n>>m>>x>>y;
		ans = 0; 
		memset(g, 0, sizeof g);
		g[x][y] = 1;
		dfs(x, y, 1);
		cout<<ans<<endl;
	}
	return 0;
}