回溯法解马的遍历问题
2012-06-08 15:36 youxin 阅读(3527) 评论(0) 编辑 收藏 举报马的遍历问题:在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)
回溯法算法设计: 搜索空间是n*M个点,约束条件是不出边界且每个点只经过一次,节点的扩展规则如上所述。
搜索过程是从任一点(x,y)出发,按深度优先原则,从8个方向尝试一个可以走的点,直到走过n*m个点。用递归容易实现。
注意:问题要求找出所有可能的解。就要注意回溯过程的清理现场工作,就是置当前位置为未经过。
数据结构设计:用一个变量dep记录递归深度,也就是走过的点数。当dep=n*m;找到一组解。
用n*m的二维数组记录马走过的过程,初始值为0表示未经过,起点存储的是1,终点存储的是n*m。
#include<iostream> using namespace std; void output(); int n=5,m=4; int fx[8]={1,2,2,1,-1,-2,-2,-1}; int fy[8]={2,1,-1,-2,-2,-1,1,2}; int a[5][4]; //下标从1开始 int dep,x,y,count; bool check(int x,int y) { if(x>=1&&x<=n&&y>=1&&y<=m&&(!a[x][y])) return true; else return false; } void find(int x,int y,int dep) { int i,xx,yy; for(i=1;i<=8;i++) //加上方向增量,形成新的坐标 { xx=x+fx[i]; yy=y+fy[i]; if(check(xx,yy)) //判断新坐标是否出界,是否已走过 { a[xx][yy]=dep; if(dep==n*m) output(); else find(xx,yy,dep+1); a[xx][yy]=0; //回溯,恢复未走未走 } } } void output() { count++; cout<<"\n"; cout<<"count="<<count; for(y=1;y<=n;y++) { cout<<endl; for(x=1;x<=m;x++) cout<<a[y][x]<<ends; } } int main() { int i,j; count=0; dep=1; cout<<"please input x,y"; cin>>x>>y; if(x>n||y>m||x<1||y<1) { cout<<"input error"; return -1; } for(i=1;i<=n;i++) for(j=1;j<=m;j++) a[i][j]=0; a[x][y]=1; find(x,y,2); if(count==0) cout<<"no solution!"; else cout<<"nambers of solution="<<count<<endl; }
代码输出好像有错误。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通