算法竞赛入门经典 习题6-4

UVa439

Knight Moves

给定起点和终点,求出骑士从起点移动到终点的最小步数。

题目中的骑士应该是国际象棋中的骑士,也就是和中国象棋中的马的走法是类似的。求最短距离,用广搜就好了。

不得不说方向向量确实好用,能避免很多错误。

#include <iostream>
#include <array>
#include <deque>
#include <string>
#include <vector>

using namespace std;

struct Node
{
	int row, col;
	size_t step;
	Node(int r, int c, size_t step) : row(r),col(c), step(step){}
};

class Solution
{
public:
	Solution(const string &start, const string &end)
		: board(8, vector<bool>(8, false)), shortest(0)
	{
		StartCol = start[0] - 'a';
		StartRow = start[1] - '1';
		EndCol = end[0] - 'a';
		EndRow = end[1] - '1';
		FindShortestPathLength();
	}
	int ShortestPathLength()
	{
		return shortest;
	}
private:
	vector<vector<bool>> board;
	int StartRow, StartCol, EndRow, EndCol;
	int shortest;
	bool onBoard(int row, int col)
	{
		return 0 <= row && row < 8 && 0 <= col && col < 8;
	}
	void FindShortestPathLength()
	{
		const vector<array<int, 2>> directions = {
			{ 1, 2 }, { -1, 2 },
			{ 2, -1 }, { 2, 1 },
			{ -1, -2 }, { 1, -2 },
			{ -2, -1 }, { -2, 1 } };
		board[StartRow][StartCol] = true;
		deque<Node> deq;
		deq.emplace_back(StartRow, StartCol, 0);
		while (!deq.empty()) {
			auto curr = deq.front();
			deq.pop_front();
			if (curr.row == EndRow && curr.col == EndCol) {
				shortest = curr.step;
				break;
			}
			for (const array<int, 2> &dir : directions)
			{
				Node node{ curr.row + dir[0],curr.col + dir[1], curr.step + 1 };
				if (onBoard(node.row, node.col) && !board[node.row][node.col]) {
					board[node.row][node.col] = true;
					deq.push_back(node);
				}
			}
		}
	}
};

int main()
{
	string start, end;
	while (cin >> start >> end) {
		Solution solution(start, end);
		cout << "To get from " << start << " to " << end << " takes "
			<< solution.ShortestPathLength() << " knight moves." << endl;
	}
	return 0;
}
/*
e2 e4
a1 b2
b2 c3
a1 h8
a1 h7
h8 a1
b1 c3
f6 f6
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值