图5

五、在n*n(5<n<15)的象棋棋盘的某一位置上放置一个马,然后采用象棋中“马走日字”的规则,判断这个马是否能不重复地走完n的平方个格子,如果能走,则给出一条马所走地轨迹。

输入格式:

输入一行,共三个数n,x,y,n(5<n<15)表示棋盘的大小,(x,y)表示马开始的位置。

输出格式:

如果能走遍棋盘,则输出n的平方行,每行两个整数,表示每一步马走的位置;如果不能走遍,则输出-1。

算法思想:从起点开始,遍历跳到以该点为中心的5x5宫格上的点(排除自己),如果不符合跳马规则退回,如果跳到绝路退回,同时如果该点周围的所有点都退回则从该点退回,当遍历的点的个数达到棋盘所有顶点数结束递归搜索成功,如果退回到起点或者到达搜索限制次数则搜索失败。

看不懂

//深度优先搜索实现
#include <iostream>
using namespace std;
#include <Math.h>

#define size 8//定义期盼的规模4x4
#define maxStep 100000//最大的步数,超出结束运行

struct node{
	bool visited;//结点是否被访问过,false表示new,true表示old
	int num;//访问编号,即马走的第几步
	//int symbol;//为每一个点特定编号
};
int static step = 0;//已正确走的步数
int static sumStep = 0;//总共走的步数,包括走错的、后退的
node chessBoard[size+1][size+1];//定义棋盘数组,第一行、第一列不用

void initChess()//初始化棋盘,使每一个点都标识new没被访问过,编码为零
{
	//int sym = 1;
        for(int i=1;i<=size;i++)
			for(int j=1;j<=size;j++){
				chessBoard[i][j].visited = false;
				chessBoard[i][j].num = 0;
			//	chessBoard[i][j].symbol = sym;//按行依次标号
				//sym++;
			}
}

void printChess()//一行一行的输出
{
        for(int i=1;i<=size;i++)
        {
                for(int j=1;j<=size;j++)
                        cout << chessBoard[i][j].num<<'\t';
                cout << endl;
        }
}

int searchX(int step)//查找某一步的列数(x坐标)
{
        for(int i=0;i<size;i++)
                for(int j = 0;j<size;j++)
                        if(chessBoard[j][i].num == step)
							return i;
        return 0;
}

int searchY(int step)//查找某一步行数(y坐标)
{
        for(int i=0;i<size;i++)
                for(int j = 0;j<size;j++)
                        if(chessBoard[j][i].num == step)
							return j;
        return 0;
}

bool isSun(int x1,int y1,int x2,int y2)//判断(x1,y1)和(x2,y2)之间的格子是否能拼成"日"字
{
	if(abs(x1-x2)==2&&abs(y1-y2)==1||abs(x1-x2)==1&&abs(y1-y2)==2)
		return true;
	else
		return false;
}

bool jumpRule(int a,int b,int x,int y)//马的前进规则,判断可不可以从(a,b)跳到(x,y)点
{
        if(x>=1 && x<=size && y>=1 && y<=size && (chessBoard[x][y].visited == false) && isSun(a,b,x,y))
                return true;
        else
                return false;
}

void jump(int x,int y)//让马跳到(x,y)
{
	++step;//步数加1
	chessBoard[x][y].num = step;//为马当前所在的点编号
	chessBoard[x][y].visited = true;//标记为old
	sumStep++;
}

void retreat(int x,int y)//从(x,y)后退一步
{
	chessBoard[x][y].visited = false;
	chessBoard[x][y].num = 0;
	--step;
	sumStep++;
}
//返回以(x,y)为中心的5x5宫格的边界下标
int leftOrUp(int x)
{
	if(x-1>=1)
	{
		if(x-2>=1)
			return x-2;
		return x-1;
	}
	return x;
}
int rightOrDown(int x)
{
	if(x+1<=size)
	{
		if(x+2<=size)
			return x+2;
		return x+1;
	}
		return x;
}
//最关键函数:(存在问题,递归可能不对,有时间再改,有大神帮忙改的话那也是极好的^_^)
void selectToJump(int x,int y)//从(x,y)自己选择跳到下一个可行的点,递归下去
{ 
	//在以(x,y)为中心的5x5宫格内的点里面选择,走得通的话以下一个点为中心继续搜索
	//要是能避免重复走已经不可行的点最好
	for(int i = leftOrUp(x);i<=rightOrDown(x);i++)//x坐标/列
		for(int j = leftOrUp(y);i<=rightOrDown(y);j++)//y坐标/行
		{
			if(!(j==x&&i==y))//排除中心点本身
			{
			jump(j,i);
			if(step==size*size || sumStep>=maxStep)//搜索成功结束或失败结束
				return;
			if(jumpRule(x,y,j,i))
				selectToJump(j,i);//以下一个点为中心继续搜索
			else
				retreat(j,i);
			}
		}
		retreat(x,y);
		if(chessBoard[x][y].visited==false)
		{
			cout<<"搜索失败!"<<endl;
			return;
		}
}
//*********************************
int main()
{
	int x,y;//起点坐标
	cout<<"请输入起点坐标(x,y):"<<endl;
	cin>>x>>y;
	//访问起点:
	++step;//起点设置为第一步
	chessBoard[x][y].num = step;//为马当前所在的点编号
	chessBoard[x][y].visited = true;//标记为old
    //selectToJump(x,y);
	//if(step == size)
		printChess();
	//else
		cout<<"搜索失败,请重试!"<<endl;
	//函数测试:
cout<<leftOrUp(1)<<'\t'<<rightOrDown(1)<<endl;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值