回溯法之马的遍历问题(递归)

马的遍历问题:在n*m的棋盘上,马只能走日字。马从位置(x,y)处出发,把棋盘的每一点都走一次,且只走一次,找出所有路径。
问题分析:行n,列m,马在不出边界的情况下有8个方向可以行走(走日字),如当前坐标为(x,y),则行走后的坐标可以为:
(x+1,y+2) (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)
在这里插入图片描述

回溯法算法设计: 搜索空间是nM个点,约束条件是不出边界且每个点只经过一次,节点的扩展规则如上所述。
搜索过程是从任一点(x,y)出发,按深度优先原则,从8个方向尝试一个可以走的点,直到走过n
m个点。用递归容易实现。
注意:问题要求找出所有可能的解。就要注意回溯过程的清理现场工作,就是置当前位置为未经过。
数据结构设计:用一个变量dep记录递归深度,也就是走过的点数。当dep=nm;找到一组解。
用n
m的二维数组记录马走过的过程,初始值为0表示未经过,起点存储的是1,终点存储的是n*m。

#include<stdio.h>
const int n=5,m=4;
int fx[8]={1,2,2,1,-1,-2,-2,-1};//定义马走的8个方向
int fy[8]={2,1,-1,-2,-2,-1,1,2};
int A[n+1][m+1];//如果为0表示当前节点未经过,非0值a表示该节点为走的第a步
int dep,x,y,numbers=0;//分别表示第几步、横坐标、纵坐标、满足条件的棋盘数

bool check(int x,int y)
{
	if(x>=1 && x<=n && y>=1 &&y<=m && (!A[x][y]))
		return true;
	else
		return false;
}

void output()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			printf("%d ",A[i][j]);
		}
		printf("\n");
	}
	printf("----------\n");
}

void solve(int x,int y,int dep)
{
	int i,xx,yy;
	for(i=0;i<=7;i++)
	{
		xx=x+fx[i];
		yy=y+fy[i];
		if(check(xx,yy))
		{
			A[xx][yy]=dep;
			if(dep==n*m)//当步数达到n*m时表示已走完每一个节点
			{
				numbers++;
				output();	
			}
			else
			{
				solve(xx,yy,dep+1);
			}
			A[xx][yy]=0;//将走过的点重置为未走过
		}
	}
}

int main()
{
	printf("please input x and y:\n");
	scanf("%d %d",&x,&y);
	if(x>n||y>m||x<1||y<1)
    {
        printf("input error\n");
    }
	else
	{
		printf("----------\n");
		A[x][y]=1;
	    solve(x,y,2);
	    printf("%d\n",numbers);
	}
}
  • 8
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
回溯法遍历问题的复杂度分析需要考虑以下几个因素: 1. 棋盘的大小:设棋盘大小为 $n \times m$,则遍历问题的规模为 $nm$。 2. 起始位置的选择:由于法具有对称性,因此可以假设起始位置为 $(0, 0)$,并对其它起始位置进行对称理。这样可以减少起始位置的选择,但并不会影响问题的复杂度。 3. 法:每个格子可以选择的下一个格子最多有 $8$ 个,因此每个格子最多需要尝试 $8$ 次才能找到一个可行的下一个格子。 4. 剪枝优化:在实际的实现,可以使用一些剪枝优化来减少回溯的次数,例如可以按照下一个格子能够到达的未访问过的格子数量从小到大进行排序,这样可以优先选择能够到达较少未访问过的格子的下一个格子。 根据以上因素,回溯法遍历问题的复杂度可以分析如下: - 时间复杂度:设棋盘大小为 $n \times m$,则回溯法遍历问题的时间复杂度为 $O(8^{nm})$,因为每个格子最多需要尝试 $8$ 次才能找到一个可行的下一个格子,而遍历所有格子需要尝试的次数是指数级别的。 - 空间复杂度:回溯法遍历问题的空间复杂度取决于递归调用栈的深度,即最多需要保存 $nm$ 个格子的信息。因此空间复杂度为 $O(nm)$。 需要注意的是,由于回溯法遍历问题的时间复杂度是指数级别的,因此对于较大的棋盘来说,回溯法是无法在合理的时间内得到解决的。在实际应用,需要考虑使用其它更加高效的算法来解决遍历问题
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值