马走日模型出现在DFS和数学推导两大方向:
可根据数据范围快速区分,数据范围极小时可想到用dfs暴搜;若数据过大导致DFS爆掉,故可通过模拟找到数学规律,分类求解(牛客)。
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;
}