骑士聚会问题(PPT截取)

在N*N的棋盘上放m个马,问各自跳多少步才能在某处聚在一起,希望聚会时间越早越好,且总步数最少。

PS.队列

用结构体数组来表示队列

struct qtype //定义有两个成员的结构
{
	int x,y;	//成员x和成员y
}
queue[T*T+20],rec[T*T+20];
	//定义数组queue和数组rec是结构类型的
	//queue是结构数组,作队列用,T=5
	//rec是结构数组,用来存储骑士们在棋盘上的起始位置
void init()
{
	//init
	memset(best,-1,sizeof(best));		//初始化数组元素均为-1
	int i=0;
	rec[i].x=0;
	rec[i].y=0;	//第0号骑士的x,y坐标点
	best[i][rec[i].x][rec[i].y]=0;	//将第0号骑士在棋盘上的跳步信息置为0,表示此处为出发点
}	//init
//假定只有一个骑士i(i=0)
void BFS()
{
	//BFS()
	//骑士的坐标点在rec[i].x和rec[i].y
	int head=1;	//定义队头head,并初始化为1
	int tail=1;	//定义队尾tail,并初始化为1
	queue[head].x=rec[i].x;	//让骑士的坐标点x入队
	queue[head].y=rec[i].y;	//让骑士的坐标点y入队
	int step=0;	//定义马的跳步数step,初始化为0
	int m=head;	//定义中间变量m,记住队头head
	while(m<=tail)	//从队头m到队尾tail进行扩展,直到队空为止,扩展过程tail会不断增加
	{
		//while
		int sq=tail;	//让sq记住原来的队尾tail
		for(int am=m;am<=sq;am++)	//m到sq作为一层扩展
		{
			//for am
			for(int k=0;k<8;k=k+1)	//枚举k,k为跳步方向
			{
				//for k
				//从(x,y)点沿k方向跳至(x1,y1)
				int x1=queue[am].x+dx[k];
				int y1=queue[am].y+dy[k];
				if(okjump(i,x1,y1))	//	判第i号骑士能否跳至(x1,y1)的跳步信息
				{	//if
					tail=tail+1;	//队尾加1
					queue[tail].x=x1;	//让x1入队
					queue[tail].y=y1;
					best[i][x1][y1]=step+1;
				}	//if
			}	//for k
		}	//for am 从m到sq作为一层已扩展完毕
		//之后,将下一段的开始sq+1赋给m,m是待扩展的段头,段尾是新扩展出的tail
		m=sq+1;
		//扩展下一层时,是从step加1的步数开始的
		step=step+1;
	}	//while
}	//BFS()
//可跳步的判别函数
bool okjump(int i,int x,int y)
{
	return(x>=1&&x<=4&&y>=1&&y<=4&&best[i][x][y]==-1);
}	//如果马跳至棋盘界内且该处尚未有马跳到过,则返回true,否则返回false
void display()
{
	//display
	for(x=0;x<5;x++)	//从0,1,...,4枚举x
	{
		//for x
		cout<<endl;	//换行
		for(y=0;y<5;y++)	//从0,1,...,4枚举y
		{
			count<<best[i][x][y]<<" ";
		}	//输出第i个骑士跳至坐标点(x,y)上的步数
	}	//for x
	cout<<endl;
}	//display
int main()
{
	init();	//初始化
	BFS();	//宽度优先扩展结点
	display();	//显示棋盘中的跳步信息
	return 0;
}

8*8,n个骑士,每次一步,跳步按中国象棋的马来跳

55
0号骑(0,0)
|0|3|2|3|2|
|3|4|1|2|3|
|2|1|4|3|2|
|3|2|3|2|3|
|2|3|2|3|4|
1号骑(1,4)
|3|2|1|2|3|
|2|3|2|3|0|
|3|2|1|2|3|
|2|3|4|1|2|
|3|2|3|2|3|
2号骑(1,2)
|1|2|3|2|1|
|2|3|0|3|2|
|1|2|3|2|1|
|4|1|2|1|4|
|3|2|3|2|3|
3号骑(3,4)
|3|2|3|2|3|
|2|3|4|1|2|
|3|2|1|2|3|
|2|3|2|3|0|
|3|2|1|2|3|
n个人中的最多跳步 good[x][y].max
n个人的跳步总和 good[x][y].sum
x,y=0,1,…,T-1
min=min{good[x][y].max}
{x,y}
x,y=0,1,…,T-1
if(good[x][y].max==min)
sum=min{good[x][y].sum}
{x,y}
x,y=0,1,…,T-1
88

#include<iostream>
#include<memory>
#include<iomanip>
using namespace std;
const T=8;	//	棋盘尺寸
const dx[8]={1,2,2,1,-1,-2,-2,-1},	//8个跳步方向上的x增量
	dy[8]={-2,-1,1,2,2,1,-1,-2};	//8个跳步方向上的y增量
int n;	//骑士数目n
int x,y;	//定义棋盘坐标x和y,全局变量
struct qtype
{
	int x,y;
}
queue[T*T],rec[T*T];
//3维数组
int best[T*T][T][T];
struct jtype
{
	int sum;
	int max;
}
good[T][T];
void init()
{
	//init
	memset(best,-1,sizeof(best));
	count<<"输入骑士数目n=";
	cin>>n;
	for(int i=0;i<n;i++)
	{
		//for i
		cout<<"第"<<i<<"号骑士位置x=";
		cin>>rec[i].x;
		cout<<"第”<<i<<"号骑士位置y=";
		cin>>rec[i].y;
		best[i][rec[i].x][rec[i].y]=0;
	}	//for i
}	//init
bool okjump(int i,int x,int y)	//可跳步的判别函数
{
	return (x>=0&&x<T&&y>=0&&y<T&&best[i][x][y]==-1);
}
void BFS()
{
	 //BFS()
	 for(int i=0;i<n;i++)
	 {
	 	//for i;
	 	int head=1; //定义队头head,并初始化为1
 		int tail=1; //定义队尾tail,并初始化为1
 		queue[head].x=rec[i].x; //让骑士的坐标点x入队
 		queue[head].y=rec[i].y; //让骑士的坐标点y入队
 		int step=0; //定义马的跳步数step,初始化为0
 		int m=head; //定义中间变量m,记住队头head
 		while(m<=tail)
 		{
  			//while
  			int sq=tail; //让sq记住原来的队尾tail
 			for(int am=m;am<=sq;am++) //m到sq作为一层扩展
 			{
   				//for am
   				for(int k=0;k<8;k=k+1) //枚举k,k为跳步方向
   				{
    					//for k
    					//从(x,y)点沿k方向跳至(x1,y1)
    					int x1=queue[am].x+dx[k];
    					int y1=queue[am].y+dy[k];
    					if(okjump(i,x,y1))
    					{ //if
    						tail=tail+1; //队尾加1
     						queue[tail].x=x1; //让x1入队
    						queue[tail].y=y1;
     						best[i][x1][y1]=step+1;
   					} //if
  				}//for k
  			} //for am 从m到sq作为一层已扩展完毕
  			//之后,将下一段的开始sq+1赋给m,m是待扩展的段头,段尾是新扩展出的tail
  			m=sq+1;
  			//扩展下一层时,是从step加1的步数开始的
  			step=step+1;
 		} //while
 	}for i
} //BFS()
void display
{	//display
	for(int i=0;i<n;i++)
	{	//for i
 		for(x=0;x<t;x++)
 		{	//for x
 			cout<<endl;
 			for(y=0;y<T;y++)
 			{
 				cout<<best[i][x][y]<<" ";
 			}
 		}	//for x
 		cout<<endl;
 	}	//for i
 }	//display
 void output_good()
 {
 	cout<<"============================="<<endl;
 	for(int i=0;i<T;i++)
 	{
 		for(int j=0;j<t;j++)
 			cout<<good[i][j].max<<' ';
 		cout<<endl;
 	}
 	cout<<"============================="<<endl;
 }
 void search()
 {	//search
	BFS();
	int minx,miny;
	for(x=0;x<T;x++)
		for(y=0;y<T;y++)
		{	//for y
			good[x][y].sum=0;
			good[x][y].max=-1;
			cout<<endl;
			for(int j=0;j<n;j++)
			{	//for j
				good[x][y].sum=good[x][y].sum+best[j][x][y];
				if(best[j][x][y]>good[x][y].max)
					good[x][y].max=best[j][x][y];
			}	//for j
		}	//for y
	cout<<"y:0 1 2 3 4 5 6 7"<<endl;
	cout<<"x:";
	for(x=0;x<T;x++)
	{	//for x
		cout<<endl;
		cout<<X<<" ";
		for(y=0;y<T;y++)
		{
			cout<<"["<<good[x][y].max<<","<<setw(2)<<good[x][y].sum<<"]";
		}
	}	//for x
	cout<<endl;
	cout<<endl;	
	int min=32767;
	output_good();
	int sum;
	for(int x=0;x<T;x++)
		for(int y=0;y<T;y++)
		{	//for y
			if(good[x][y].max<min)
			{	//if
				min=good[x][y].max;
				sum=good[x][y].sum;
				minx=x;
				miny=y
			}	//if
			if(good[x][y].max==min)
			{
				if(good[x][y].sum<sum)
				{
					sum=good[x][y].sum;
					minx=x;
					miny=y;
				}
			}
		}
	}
		output_good();
		cout<<"最佳聚会位置:x="<<minx<<",y="<<miny<<endl;
		cout<<"到达聚会点最少天数为:"<<min<<endl;
		cout<<"众骑士的跳步总数为:"<<sum<<endl;
}
int main()
{
	init();
	search();
	display();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值