数据结构学习之启发式搜索求解骑士周游问题

#include <iostream>
#include "conio.h"
using namespace std;

class Board
{
private:
	int board[8][8];  //棋盘
	int step;         //当前走的步数
	int No;	          //当前解的编号
	int direct[8][2]; //各前进方向的坐标偏移
	int wayCount[8][8];  //棋盘上每个位置可跳出的方向数目
	int startX;          //起始点坐标x
	int startY;			//起始点坐标y
	int dir[8][8][8];   //保存最优的搜索方向顺序
	

	void init() 
	{ 
		int i,j,k;
		int x,y;
		//确定从棋盘上每个位置可跳出的方向数目
		for(j=0;j<8;j++)
		{
			for(i=0;i<8;i++) 
			{
				wayCount[j][i]=0;
				for(k=0;k<8;k++) 
				{  
					x=i+direct[k][0]; 
					y=j+direct[k][1];
					if(check(x,y)) 
						wayCount[j][i]++; 
				} 
			}
		}

		//为棋盘上每个位置确定搜索的方向顺序
		for(y=0;y<8;y++)
		{
			for(x=0;x<8;x++) 
			{
				//默认搜索顺序为顺时针方向
				for(k=0;k<8;k++)
				{
					dir[y][x][k]=k;
				}
				//寻找最优搜索顺序
				for(i=0;i<7;i++)
				{
					k=i;
					int x1=x+direct[dir[y][x][k]][0];
					int y1=y+direct[dir[y][x][k]][1];
					//为各搜索方向按规则排序
					//希望搜索时优先到达下一步可能性较少的位置
					for(j=i+1;j<8;j++)
					{
						int x2=x+direct[dir[y][x][j]][0];
						int y2=y+direct[dir[y][x][j]][1];
						//如果从当前位置出发 方向j优于方向k 则将k替换为j
						if( (!check(x1,y1) && check(x2,y2))
							|| ( check(x1,y1) && check(x2,y2) &&
							wayCount[x1][y1]>wayCount[x2][y2]) )
						{
							k=j;
							x1=x+direct[dir[y][x][k]][0];
							y1=y+direct[dir[y][x][k]][1];
						}
					}
					j=dir[y][x][k];
					dir[y][x][k]=dir[y][x][i];
					dir[y][x][i]=j;
				}
			}
		}
	}

	//检查x,y是否为合法位置
	int check(int x,int y) 
	{ 
		if(x<0||x>7||y<0||y>7)
		{
			return 0;
		}
		else
		{
			return 1;
		}
	}

	//从指定位置(x,y)出发寻找路径
	void dg(int x, int y)
	{
		int i,nx,ny;
		//如果当前为最后一步 则终止递归
		if(step==64)
		{
			printPath();
			return;
		}

		//按照最优的搜索方向顺序 依次向各可能方向搜索
		for(i=0;i<8;i++)
		{
			nx=x+direct[dir[y][x][i]][0];
			ny=y+direct[dir[y][x][i]][1];
			if(nx>=0 && nx<8 && ny>=0 && ny<8)
			{
				//如果成功到达下一位置 则从新位置开始继续搜索
				if(board[ny][nx]<0)
				{
					board[ny][nx]=step;
					step++;
					dg(nx,ny);
					board[ny][nx]=-1;
					step--;
				}
			}
		}
	}

	void printPath()
	{
		int i,j;
		No++;
		cout<<"No"<<No<<":"<<endl;
		for(j=0;j<8;j++)
		{
			for(i=0;i<8;i++)
			{
				cout<<board[j][i]<<" ";
				if(board[j][i]<10) 
					cout<<" "; 
			}
			cout<<endl;
		}
		cout<<"Press anykey to continue...";
		getch();
		cout<<endl;
	}
	void printwc()
	{
		int i,j;
		No++;
		cout<<"No"<<No<<":"<<endl;
		for(j=0;j<8;j++)
		{
			for(i=0;i<8;i++)
			{
				cout<<wayCount[j][i]<<" ";
				if(wayCount[j][i]<10) 
					cout<<" "; 
			}
			cout<<endl;
		}
		cout<<"Press anykey to continue...";
		getch();
		cout<<endl;
	}

public:
	Board(int x, int y)
	{
		int i,j;
		startX=x;
		startY=y;
		direct[0][0]=1;		direct[0][1]=-2;
		direct[1][0]=2;		direct[1][1]=-1;
		direct[2][0]=2;		direct[2][1]=1;
		direct[3][0]=1;		direct[3][1]=2;
		direct[4][0]=-1;	direct[4][1]=2;
		direct[5][0]=-2;	direct[5][1]=1;
		direct[6][0]=-2;	direct[6][1]=-1;
		direct[7][0]=-1;	direct[7][1]=-2;
		step=1;
		No=0;
		for(j=0;j<8;j++)
		{
			for(i=0;i<8;i++)
			{
				board[j][i]=-1;
			}
		}
		board[y][x]=0;
	}

	void GetPath()
	{
		init();
		dg(startX,startY);
		if(No==0)
		{
			cout<<"no result"<<endl;
		}
	}
};


void main()
{
	int x,y;
	cout<<"Please input the start point (x,y)."
		<<endl<<"x=";
	cin>>x;
	getchar();
	cout<<"y=";
	cin>>y;
	getchar();
	Board board(x,y);
	board.GetPath();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值