(hdu step 4.2.3)Knight Moves(求从起点是否能够到达终点的最小步数)

题目:

Knight Moves

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 453 Accepted Submission(s): 326
 
Problem Description
A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find the shortest closed tour of knight moves that visits each square of a given set of n squares on a chessboard exactly once. He thinks that the most difficult part of the problem is determining the smallest number of knight moves between two given squares and that, once you have accomplished this, finding the tour would be easy.
Of course you know that it is vice versa. So you offer him to write a program that solves the "difficult" part. 

Your job is to write a program that takes two squares a and b as input and then determines the number of knight moves on a shortest route from a to b. 
 
Input
The input file will contain one or more test cases. Each test case consists of one line containing two squares separated by one space. A square is a string consisting of a letter (a-h) representing the column and a digit (1-8) representing the row on the chessboard. 

 
Output

            For each test case, print one line saying "To get from xx to yy takes n knight moves.".
 
Sample Input
e2 e4
a1 b2
b2 c3
a1 h8
a1 h7
h8 a1
b1 c3
f6 f6
 
Sample Output
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.
 
 
Source
University of Ulm Local Contest 1996
 
Recommend
Eddy


题目大意:

               跳马游戏。求从一个节点调到另外一个节点的最小步数。


题目分析:

               广搜。这道题基本属于广搜的裸题,已经是简单到不能再简单了。跟其他题相比,本题有以下特点:

1)这道题不需要map[][]矩阵,因为map[][]主要用于存储整个地图的信息。如某一点不可到达之类的,而这道题每一点都可以到达。所以不需要map[][]

2)这一道题的下一个节点的合法性判断只需要判断是否越界即可。以为内在这道题中不涉及“障碍物”的概念,没一点都可以到达。

3)之所以使用优先队列,是因为普通队列无法保证每次出对元素的时间(步数)最小


也就是说,这道题最大的特点就是没有障碍物。所以很多东西都不需要。


代码如下:

/*
 * c.cpp
 *
 *  Created on: 2015年2月17日
 *      Author: Administrator
 */

#include <iostream>
#include <cstdio>
#include <queue>


using namespace std;

int x1,y1;
int x2,y2;
const int inf = 999999;

int dir[8][2]={
		{-2,1},
		{-1,2},
		{2,1},
		{1,2},
		{1,-2},
		{2,-1},
		{-1,-2},
		{-2,-1}
};
bool vis[8][8];


struct Node{
	int x;
	int y;
	int step;

	friend bool operator<(Node a,Node b){//在优先队列中从小到大排序
		return a.step > b.step;
	}
};




/**
 * 在这道题中判断下一届点是否合法,
 * 只需要判断下一届点是否越界即可.
 * 因为这道题可以理解为任意节点都可访问.
 */
bool check(int x,int y){
	if(x < 0 || x >=8 || y <0 || y >= 8){
		return false;
	}
	return true;
}


int bfs(){
	priority_queue<Node> q;


	//初始化起点
	Node root;
	root.x = x1;
	root.y = y1;
	root.step = 0;
	vis[x1][y1] = 0;//到达起点的最小步数初始化为0


	Node k;
	q.push(root);
	while(!q.empty()){
		Node a = q.top();
		q.pop();

		if(a.x == x2 && a.y == y2){//如果已经到达了终点
			return a.step;//则返回到达重点所需要的步数
		}

		int i;
		for(i = 0 ; i < 8 ; ++i){//遍历该节点的所有下一级节点
			k.x = a.x + dir[i][0];//计算下一级节点的坐标
			k.y = a.y + dir[i][1];

			if(check(k.x,k.y) == false){//如果下一级结点不合法
				continue;//跳过本节点
			}

			k.step = a.step+1;//计算到当前节点所需要的步数
			if(vis[k.x][k.y] > k.step){//如果之前到达当前节点的步数>目前计算出的到达当前节点的最小步数
				vis[k.x][k.y] = k.step;//则更新到达当前节点的最小步数
				q.push(k);//将元素k入队
			}

		}
	}

	return -1;//代表终点不可到达
}


int main(){
	string start;
	string end;
	while(cin >> start >> end){//需要注意形如a1,b2这种类型的数据输入
		x1 = start[0] - 'a';
		y1 = start[1] - '1' ;

		x2 = end[0] - 'a';
		y2 = end[1] - '1';


		memset(vis,inf,sizeof(vis));

		cout << "To get from " <<start <<" to "<< end << " takes "<< bfs ()<<" knight moves." << endl;
	}

	return 0;
}







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帅气的东哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值