题目描述
描述
马在中国象棋以日字形规则移动。请编写一段程序,给定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
54 0 0
样例输出
32
题目分析
这是一道十分典型的DFS题,是迷宫的“进化版”。迷宫是往上下左右四个方向行走,同理本题即为往八个方向行走(如图2-1【我已经尽力画了。。】)
设红色坐标为[x,y],这从1-8的坐标依次是[x-1,y+2][x-2,y+1][x-2,y-1][x-1,y-2][x+1,y-2][x+2,y-1][x+2,y+1][x+1,y+2],同理,将其依次存入x[8],y[8]里。
DFS条件判断:不超出边界,不走“回头路”。
DFS退出条件:将整个棋盘摆满即摆放总个数==行*列
代码实现
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,r,i,j,k,y1,y2,q,w,sn=0;
bool b[105][105];
intx[8]={-2,-1,1,2,2,1,-1,-2},y[8]={1,2,2,1,-1,-2,-2,-1};//存储路径
bool chek(int a,int b)//判断是否超出边界函数
{
if(a<=r-1&&b<=w-1&&a>=0&&b>=0)return1;
return0;
}
void s(int str,int stw,int n)
{
if(n==r*w){sn++;return;}//判断是否已摆满
for(inti=0;i<=7;i++)
{
if((!b[str+x[i]][stw+y[i]])&&chek(str+x[i],stw+y[i]))
{
b[str+x[i]][stw+y[i]]=1;
s(str+x[i],stw+y[i],n+1);
b[str+x[i]][stw+y[i]]=0;//回溯
}
}
}
int main()
{
intx1,x2;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
sn=0;
scanf("%d%d%d%d",&r,&w,&x1,&x2);
b[x1][x2]=1;
s(x1,x2,1);
printf("%d\n",sn);
memset(b,0,sizeof(b));//一定要记住清零
}
}
后记
本人第一次写博客,请多指教^_^。
Writing by Panda Hu 2017.5.20