在8X8的棋盘上分布着n个骑士,他们想约在某一个格中聚会。骑士每天可以像国际象棋中的马那样移动一次,可以从中间像8个方向移动(当然不能走出棋盘),请计算n个骑士的最早聚会地点和要走多少天。要求尽早聚会,且n个人走的总步数最少,先到聚会地点的骑士可以不再移动等待其他的骑士。
从键盘输入n(0<n<=64),然后一次输入n个骑士的初始位置xi,yi(0<=xi,yi<=7)。屏幕输出以空格分隔的三个数,分别为聚会点(x,y)以及走的天数。
提示:BFS。
#define M 8
#define N 8
#define DIR 8
typedef struct Pointer {
int x;
int y;
};
typedef struct Knight {
Pointer* point; //起始点
bool visited[M][N]; //是否访问
queue<Pointer*> kq; //第几天到达的位置
};
//结果结构体
typedef struct Result {
Pointer* point;
int days;
};
/*x行,y列
* 下一步位移*/
int nextX[] = { -1, 1, -2, 2, -2, 2, -1, 1 };
int nextY[] = { -2, -2, -1, -1, 1, 1, 2, 2 };
/*坐标是否合理*/
bool sure(int i, int j) {
if (i >= 0 && i < M && j >= 0 && j < N)
return true;
else
return false;
}
//寻找集合点和天数
Result* findGatherPoint(vector<Knight*> knights) {
int days = 0;
//记录骑士到达数量
int matrix[M][N] = { 0 };
if (knights.empty()) {
return NULL;
}
//预处理
for (int i = 0; i < knights.size(); ++i) {
matrix[knights[i]->point->x][knights[i]->point->y] = 1;
}
while (1) {
days++;
for (int i = 0; i < knights.size(); ++i) {
int len = knights[i]->kq.size();
for (int j = 0; j < len; ++j) {
Pointer* tmp = knights[i]->kq.front();
knights[i]->kq.pop();
/*BFS向8个方向走一步*/
for (int k = 0; k < DIR; ++k) {
int x = tmp->x + nextX[k];
int y = tmp->y + nextY[k];
if (sure(x, y) && !knights[i]->visited[x][y]) {
knights[i]->visited[x][y] = true;
Pointer* p = new Pointer();
p->x = x;
p->y = y;
knights[i]->kq.push(p);
matrix[x][y]++;
if (matrix[x][y] == knights.size()) {
Result* result = new Result();
result->point = p;
result->days = days;
return result;
}
}
}
}
}
}
}