Knight Moves --- bfs 记录

问题描述
你的一个朋友正在研究旅行骑士问题 (TKP),你将在其中找到最短的骑士移动封闭路径,该路径恰好访问棋盘上给定 n 个方格中的每个方格一次。他认为问题中最困难的部分是确定两个给定方格之间的最小骑士移动数,一旦完成了这一点,找到巡回赛将很容易。
你当然知道反之亦然。所以你让他写一个解决“困难”部分的程序。
你的工作是编写一个程序,它以两个正方形 a 和 b 作为输入,然后确定从 a 到 b 的最短路线上的骑士移动次数。

输入
输入文件将包含一个或多个测试用例。每个测试用例由一行组成,其中包含两个由一个空格分隔的正方形。正方形是一个字符串,由一个代表列的字母 (ah) 和代表棋盘上的行的数字 (1-8) 组成。

输出
对于每个测试用例,打印一行“To get from xx to yy takes n knight move.”。

样本输入
e2 e4
a1 b2
b2 c3
a1 h8
a1 h7
h8 a1
b1 c3
f6 f6

样本输出
To get from e2 to e4 takes 2 knight moves.
To get from a1 to b2 takes 4 knight moves.
To get from b2 to c3 takes 2 knight moves.
To get from a1 to h8 takes 6 knight moves.
To get from a1 to h7 takes 5 knight moves.
To get from h8 to a1 takes 6 knight moves.
To get from b1 to c3 takes 1 knight moves.
To get from f6 to f6 takes 0 knight moves.

初始状态 起点坐标(st_x, st_y)
目标状态 终点坐标(ed_x, ed_y)
移动方式: r[8][2] = {{1, 2}, {2, 1}, {-2, 1}, {-1, 2}, {1, -2}, {2, -1}, {-2, -1}, {-1, -2}}
利用规则(移动方式) 生成下一层的所有状态节点,并依次放入队列中
层层往下展开,直到到达终点

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;

int st_x, st_y, ed_x, ed_y;
char s1[3], s2[3];  // 注意字符串数组最后还要存一个\0,所以多一个位置
int vis[9][9], r[8][2] = {{1, 2}, {2, 1}, {-2, 1}, {-1, 2}, {1, -2}, {2, -1}, {-2, -1}, {-1, -2}};

struct node{
	int x, y, step;
};

bool check(int x, int y) {  // 可移动到的位置,是否合法
	if(x >= 1 && x <= 8 && y >= 1 && y <= 8)
		return true;
	return false;
}

void bfs() {
	node cur, next;
	queue<node> q;
	cur.x = st_x, cur.y = st_y, cur.step = 0;  // 初始化
	vis[cur.x][cur.y] = 1;  // 标记
	q.push(cur);
	while(!q.empty()) {
		cur = q.front();
		q.pop();
		if(cur.x == ed_x && cur.y == ed_y) {  
			// 注意输出中 还有起点和终点的位置
			printf("To get from %s to %s takes %d knight moves.\n", s1, s2, cur.step);
			return;
		}
		for(int i = 0; i < 8; i++) {
			next.x = cur.x + r[i][0];
			next.y = cur.y + r[i][1];
			// 注意判断移动后的位置是否合法
			if(!check(next.x, next.y))	continue;
			if(!vis[next.x][next.y]) {
				next.step = cur.step + 1;
				vis[next.x][next.y] = 1;
				q.push(next);
			}
		}
	}
}

int main() {
	while(~scanf("%s %s", s1, s2)) {
		memset(vis, 0, sizeof(vis));
		// 将字符全部转为数字坐标
		st_x = s1[0] - 'a' + 1;
		st_y = s1[1] - '0';
		ed_x = s2[0] - 'a' + 1;
		ed_y = s2[1] - '0';
		//printf("%d %d %d %d\n", st_x, st_y, ed_x, ed_y);
		bfs();
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值