ybt1257_Knight Moves
时空限制 1000ms/64MB
【题目描述】
输入n代表有个n×n的棋盘,输入开始位置的坐标和结束位置的坐标,问一个骑士朝棋盘的八个方向走马字步,从开始坐标到结束坐标可以经过多少步。
【输入】
首先输入一个n
,表示测试样例的个数。
每个测试样例有三行。
第一行是棋盘的大小L(4≤L≤300);
第二行和第三行分别表示马的起始位置和目标位置(0..L−1)。
【输出】
马移动的最小步数,起始位置和目标位置相同时输出0。
【输入样例】
3 8 0 0 7 0 100 0 0 30 50 10 1 1 1 1
【输出样例】
5 28 0
代码
法一:STL队列
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 305;
const int dx[] = {-2,-1, 1, 2, 2, 1,-1,-2},
dy[] = { 1, 2, 2, 1,-1,-2,-2,-1};
int n,L,x1,y1,x2,y2;
bool g[N][N];
struct node{
int x,y,step;
node(){ }
node(int a,int b,int s):x(a),y(b),step(s){ }
};
void bfs(){
fill(g[0],g[0]+N*N,false); //重置标志数组
queue<node> q;
q.push(node(x1,y1,0));
g[x1][y1] = true;
while (!q.empty()){
node k=q.front(); q.pop(); //取队头,队头出队
if (k.x==x2 && k.y==y2) { cout<<k.step<<endl; return; } //到达目的坐标
for (int i=0; i<8; i++){
int x=k.x+dx[i],y=k.y+dy[i];
if (x>=0 && x<L && y>=0 && y<L && !g[x][y]){
q.push(node(x,y,k.step+1)); //入队
g[x][y] = true;
}
}
}
}
int main(){
cin>>n;
while (n--){
cin>>L>>x1>>y1>>x2>>y2;
if (x1==y1 && x2==y2) cout<<0<<endl;
else bfs();
}
return 0;
}
法二:手动队列
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 305;
const int dx[] = {-2,-1, 1, 2, 2, 1,-1,-2},
dy[] = { 1, 2, 2, 1,-1,-2,-2,-1};
int n,L,x1,y1,x2,y2,que[N*N][3],head,tail;
bool g[N][N];
void bfs(){
fill(g[0],g[0]+N*N,false);
head = tail = 0; //多笔测试要重置标志数组 队列
que[++tail][0]=0; que[tail][1]=x1; que[tail][2]=y1; //入队
g[x1][y1] = true;
while (head<tail){
head++; //取队头,队头出队
if (que[head][1]==x2 && que[head][2]==y2) { cout<<que[head][0]<<endl; return; } //到达目的坐标
for (int i=0; i<8; i++){
int x=que[head][1]+dx[i],y=que[head][2]+dy[i];
if (x>=0 && x<L && y>=0 && y<L && !g[x][y]){
que[++tail][0]=que[head][0]+1; que[tail][1]=x; que[tail][2]=y; //入队
g[x][y] = true;
}
}
}
}
int main(){
cin>>n;
while (n--){
cin>>L>>x1>>y1>>x2>>y2;
if (x1==y1 && x2==y2) cout<<0<<endl;
else bfs();
}
return 0;
}