您的位置:首页 > 其它

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

2015-02-17 12:32 633 查看
题目:

Knight Moves

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 453 Accepted Submission(s): 326
 
[align=left]Problem Description[/align]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. 
 
[align=left]Input[/align]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. 

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: