/*
马的遍历问题:
在n*m的棋盘中,马只能走“日” 字。马从位置(x,y)处出发,把棋盘的每一格都走一次,
且只走一次。找出所有路径。
问题分析:
1问题解的搜索空间?
棋盘的规模是n*m,是指行有n条边,列有m条边
马在棋盘的点上走,所以搜索控件是整个棋盘上的n*m个点
用n*m的二维数组记录马行走的过程,初值为0标识未经过。
2在寻找路径过程中,活结点的扩展规则?
对于棋盘上任意一点A(x,y),有8个扩展方向:
A(x+1,y+2),A(x+1,y-2)
A(x+2,y+1),A(x+2,y-1)
A(x-1,y-2),A(x-1,y+2)
A(x-2,y-1),A(x-2,y+1)
用数组fx[8] = {1,1,2,2,-1,-1,-2,-2},
fy[8]={2,-2,1,-1,-2,2,-1,1}来模拟马走日时下表的变化过程
问题3:扩展的约束条件?
1)不出边界
2)每个点只经过一次
棋盘点对应的数组元素初值为0,对走过的棋盘点的值置为所有步数
起点存储1,重点存储n*m
函数check,检查当前状态是否合理
问题4:搜索解空间?
搜索过程是从任一点(x,y)出发,按照深度优先原则,从8个方向
尝试一个可以走的棋盘点,直到走过棋盘上所有n*m个点。递归算法
注意要求找出全部可能的解,注意回溯过程的清理现场工作,也就是
置当前位置为未经过
数据结构设计:
1)用一个变量dep记录递归深度=走过的点数,当dep=n*m时,找到一族解
2)用n*m的二维数组记录马行走的过程,初始值为0标识未经过。搜索完毕后,
起点存储的是1,终点存储的是n*m
输入:
10 9
4 4
输出:
//未解决
*/
#include <stdio.h>
#include <string.h>
const int MAXSIZE = 100;
int g_count;
//方向数组
//int g_x[8] = {1,1,2,2,-1,-1,-2,-2};
//int g_y[8] = {2,-2,1,-1,-2,2,-1,1};
int g_x[8]={1,2,2,1,-1,-2,-2,-1};
int g_y[8]= {2,1,-1,-2,-2,-1,1,2};
//记录所走的顺序
int g_path[MAXSIZE][MAXSIZE];
void print(int n,int m)
{
g_count++;
for(int i = 0 ; i < n ; i++)
{
for(int j = 0 ; j < m ; j++)
{
printf("%d ",g_path[i][j]);
}
printf("\n");
}
printf("\n");
}
//已经拥有深度,同时兼顾了计数的功能,因此,无需再进行计数
void dfs(int x,int y,int iDepth,int n,int m)
{
int xx,yy;
//迷宫算法典型步骤,一上来就是方向的扩展
for(int i = 0 ; i < 8 ; i++)
{
//获取新方向
xx = x + g_x[i];
yy = y + g_y[i];
//剪枝:是否越界
if(xx < 0 || xx >= n || yy < 0 || yy >= m)
{
continue;
}
//剪枝:是否访问过
if(g_path[xx][yy] != 0)
{
continue;
}
//设定新方向的存储值
g_path[xx][yy] = iDepth;
//判断是否达到递归出口
if(iDepth == n*m)
{
//return ;
//注意,这里要走出所有路径,因此不能返回,而是输出
print(n,m);
}
//如果没有到达递归出口
else
{
//递归
dfs(xx,yy,iDepth+1,n,m);
//置已访问标记为未访问
//g_path[xx][yy] = 0;
}
}
//置已访问标记为未访问
g_path[xx][yy] = 0;
//iDepth--;
}
void process()
{
int n,m;
while(EOF != scanf("%d %d",&n,&m))
{
//让用户输入想走的位置
//int ix = 0;
//int iy = 0;
//scanf("%d %d",&ix,&iy);
for(int ix = 0 ; ix < n ; ix++)
{
for(int iy = 0 ; iy < m ; iy++)
{
g_count = 0;
//关键,初始深度为1,所以调用的时候从第二个节点开始走,因此赋予深度为2
int iDepth = 2;
memset(g_path,0,sizeof(g_path));
//设定初始节点记录值为1
g_path[ix][iy] = 1;
dfs(ix,iy,iDepth,n,m);
//print(n,m);
if(g_count == 0)
{
printf("x=%d,y=%d,没有答案\n",ix,iy);
}
else
{
printf("x=%d,y=%d,答案个数为:%d\n",ix,iy,g_count);
}
}
}
}
}
int main(int argc,char* argv[])
{
process();
getchar();
return 0;
}
//#include <stdio.h>
//#include <iostream>
//#include <stdlib.h>
//
//using namespace std;
//const int n=10;
//const int m=9;
//int a[n][m];
//int dep;
//
//int g_count;
//
//int fx[8]={1,2,2,1,-1,-2,-2,-1};
//int fy[8]={2,1,-1,-2,-2,-1,1,2};
//
//void output()
//{
// g_count= g_count+1;
// cout << endl;
// cout << "count =" << g_count << endl;
// for (int x=1;x<=n;x++)
// {
// for(int y=1;y<=m;y++)
// {
// cout << a[x][y] << "\t";
// }
// cout << endl;
// }
//}
//
//bool check(int xx,int yy)
//{
// if(yy >n || xx >m || xx < 1 || yy <1)
// {
// return false;
// }
// if(a[xx][yy] != 0)
// {
// return false;
// }
// return true;
//}
//
//void find(int x,int y,int dep)
//{
// int xx,yy;
// for (int 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; //回溯,恢复未走标志
//}
//
//int main(int argc,char* argv[])
//{
// int count=0;
// dep=1;
// printf("input x,y\n");
// //int x,y;
// //while(cin >> x >> y)
// //{
// for(int x = 1 ; x <= n ; x++)
// {
// for(int y = 1 ; y <= m ;y++)
// {
// if (x > n || y > m || x < 1 || y < 1)
// {
// cout << "无效的输入" << endl;
// return 0;
// }
// memset(a,0,sizeof(a));
// a[x][y]=1;
// find(x,y,2);
// if (count ==0 )
// {
// cout << "x = " << x << ",y = ," << y << "No answer" << endl;
// }
// else
// {
// cout << "x = " << x << ",y = ," << y << "count=" << count << endl;
// }
// }
// }
//
// //}
// getchar();
// system("pause");
// return 0;
//}
算法设计与分析:第五章 回溯法 5.5马的遍历
原文作者:回溯法
原文地址: https://blog.csdn.net/qingyuanluofeng/article/details/47189427
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/qingyuanluofeng/article/details/47189427
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。