马走日(题解)
马走日
题目描述:
马在中国象棋以日字形规则移动。
请编写一段程序,给定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
5 4 0 0
样例输出:
32
分析:
此题可以使用深度优先搜索(DFS)进行走棋模拟。
对于如何走日字型,可以用到“方向数组”,一个(dx[])控制x坐标变化,一个(dy[])控制y坐标变化。然后在对应(下标相同的)位置写上数字,使dx[i]+dy[i]正好能实现一个日字走棋:
int dx[]={-2,-1,1,2,2,1,-1,2};
int dy[]={1,2,2,1,-1,-2,-2,-1};
接下来就是DFS阶段了:
void dfs(int x,int y,int s){//x,y表示起始位置,s表示步数
if(s==n*m){//s为n*m则表示走过了全部的格子(步数=格数)
ans++;
return ;
}
for(int i=0;i<8;i++){
int xx=x+dx[i];
int yy=y+dy[i]; //走一步
if(xx>=0&&xx<n&&yy>=0&&yy<m&&(vis[xx][yy]==false)){//不越界且不重叠
vis[xx][yy]=true;//标记走过的
dfs(xx,yy,s+1);//从当前步继续往后看,步数要加1
vis[xx][yy]=false;//回溯。
}
}
}
关于DFS的原理,上述注释已给出解释,至于深搜的相关实现方法在此不在赘述。可参考此文章:基础搜索
最后加上主函数便完成了:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=15;
bool vis[N][N];
int t,n,m,x,y,ans=0;
int dx[]={-2,-1,1,2,2,1,-1,-2};
int dy[]={1,2,2,1,-1,-2,-2,-1};
void dfs(int x,int y,int s){//x,y表示起始位置,s表示步数
if(s==n*m){//s为n*m则表示走过了全部的格子(步数=格数)
ans++;
return ;
}
for(int i=0;i<8;i++){
int xx=x+dx[i];
int yy=y+dy[i]; //走一步
if(xx>=0&&xx<n&&yy>=0&&yy<m&&(vis[xx][yy]==false)){//不越界且不重叠
vis[xx][yy]=true;//标记走过的
dfs(xx,yy,s+1);//从当前步继续往后看,步数要加1
vis[xx][yy]=false;//回溯。
}
}
}
int main(){
cin>>t;
while(t--){
ans=0;
memset(vis,false,sizeof vis);
cin>>n>>m>>x>>y;
vis[x][y]=true;//起点被标为true.
dfs(x,y,1);
cout<<ans<<endl;
}
return 0;
}
本文作者:小坦js
本文链接:https://www.cnblogs.com/xiaotan-js/p/16610877.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步