算法基础入门:马走日

(如有错请指出,感谢)

题目:马走日

一、问题描述

马在中国象棋以日字规则移动
请编写一段程序,给定n×m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。

二、课题分析

1.问题解决思路

不重复地经过棋盘上任何一个点,即同一个点不能走两次,能用马走完棋盘上的所有点。要求输出的不是可以不可以,要求输出的是路径总数,即从某个点出发完成的路径总数有多少条。那么需要对走过的地方进行回溯,重新让这个点变得可用,这样我们才有可能找到一条新的路径,多了一种可能。然后需要依次查找里面,需要数组来标记走过或者没走过。如果走过了不能再走(不走回头路)。然后画图,将每个点都标出来,这样写偏移量数组不会写错。若偏移量数组写错,最后这个结果一定是错的。

2.功能模块详述

搭建一个Main函数框架;
搭建一个dfs函数框架

三、算法描述

回溯算法递归实现:
1.给n,m,sx,sy赋值;
2.调用递归函数dfs(sx,sy,1);
3.将第一组j分别加到x,y坐标上,即将马的x,y坐标变为下一步八种跳法中的第一种,遍历8个方向后,得到新的坐标,判断新坐标有没有出界:若xx>=0表示从0开始;若xx < 0 或者 xx >= n 或者yy < 0 或者 yy >= m,则表示越界了,越界则跳过;若该点没有越界,就判断能不能走,表示这个点没有走过则令v[x][y]=0;
4.若符合题意,则继续递归调用,此时马在第二步,所以递归i调用时马的步数step变为step+1;
5.重复上述步骤;
6.若是某一层次递归调用完毕,则开始回溯,此时有两种情况:一种是此种跳法无法遍历地图上所有点,另一种是此法已经遍历完地图上所有点。无论哪一种情况,开始回溯时,应该将跳过的所有点变为可跳点,因为这些点已经跳过了,所以此时v[x][y]=0,此时要v[x][y]变为1,否则将无法回溯。

四、源程序

#include <bits/stdc++.h>
using namespace std;
int n, m, sx, sy, cnt;
bool v[15][15];
int dx[8] = { -2,-2,-1,1,2,2,1,-1 },//偏移量数组
dy[8] = { 1,-1,-2,-2,-1,1,2,2 };//x和y一一对应
void dfs(int x,int y,int step){//写一个dfs函数:起点坐标和步数
	if (step == n * m){//走过的步数等于所有的格子(判断有没有结束)
			cnt++;//找到了一种方案
		return;
}
	for (int i = 0; i < 8; i++){//遍历8个方向
		int xx = x + dx[i];
		int yy = y + dy[i];//拿到新的坐标(xx,yy)
		if (xx < 0 || xx >= n || yy < 0 || yy >= m)//判断新坐标有没有出界:若xx>=0表示从0开始;若xx < 0 或者 xx >= n 或者yy < 0 或者 yy >= m,则表示越界了
			continue;//越界了,跳过
			if (v[xx][yy] == 0){//若该点没有越界,就判断能不能走,表示这个点没有走过则=0
				v[xx][yy]=1;//表示走过
					dfs(xx,yy,step+1);//去下一格
					v[xx][yy]=0;//取消标记,回溯(这个点重新开放可以走)
			}
	}
}

int main(){//搭建main函数框架
	int t;
	cin >> t;//t次输入
	while (t--){
		memset(v, 0, sizeof(v));//初始化输入
		cnt = 0;
		cin >> n >> m >> sx >> sy;
		v[sx][sy] = 1;//标记起点已走过
		dfs(sx, sy, 1);//从起点(sx,sy)出发,步数为1
		cout << cnt << endl;//输出cnt
	}
	return 0;
}

实验结果:
1
5 4 0 0
32

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ddj-sun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值