题目描述
总时间限制: 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
题解思路
这道题参考的是dfs算法,简单描述一个dfs过程就是:从一个状态a开始,能往下一个状态b转移,就随机选择下一个状态,对下一个状态执行dfs(b),如果a的所有状态都已经走过了,就回退到调用dfs(a)的地方。
那么在解决这道题是怎样使用dfs的呢?
假设一个状态由(x, y, steps)表示,x, y, 表示棋子在棋盘的位置,steps表示相对于初始位置走的步数,dfs的边界条件就是 steps == n*m,即遍历了所有格子(因为每次状态转移都不选择之前已经走过的点),状态转移方式就是从当前的状态跳转到棋子能够走到的下一个没有走过的点,对其调用dfs, steps的值加一。
解题代码
#include <cstring>
#include <cstdio>
//#include <queue>
int c[10][10];
int flags[10][10];
int n, m, x, y;
int sum;
int dy[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dx[8] = {1, 2, 2, 1, -1, -2, -2, -1};
void dfs(int x, int y, int steps){
if(steps == n*m){
sum++;
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 && !flags[xx][yy]){
flags[xx][yy] = 1;
dfs(xx, yy, steps + 1);
flags[xx][yy] = 0;
}
}
}
int main(){
int t;
scanf("%d", &t);
while(t--){
memset(c, 0 ,sizeof(c));
memset(flags, 0, sizeof(flags));
scanf("%d%d%d%d", &n, &m, &x, &y);
sum = 0;
flags[x][y] = 1;
dfs(x, y, 1);
printf("%d
", sum);
}
return 0;
}