在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;
}