队列queue
队列只允许从队尾入队、从队头出队,不允许再中间位置插入和删除,不支持数组表示法和随机访问。使用queue
时需要引入头文件#include<queue>
。
queue<int> q
:创建一个空队q
,数据类型为int
push(x)
:x
入队pop()
:出队front()
:取队头(未出队)empty()
:判断队列是否为空,若为空,则返回true
size()
:求队列大小,返回队列中的元素个数。
题目描述
写程序,计算骑士从一个位置移动到另一个位置所需的最少移动次数。骑士移动的规则如图所示。
输入:输入的第1行为测试用例个数N
。每个测试用例都包含3行。第1行表示棋盘的长度
L
(
4
≤
L
≤
300
)
L(4 \leq L \leq 300)
L(4≤L≤300),棋盘的大小为
L
×
L
L \times L
L×L;第2行和第3行包含一对
{
0
,
.
.
.
,
L
−
1
}
×
{
0
,
.
.
.
,
L
−
1
}
\{0,...,L-1\} \times \{0,...,L-1\}
{0,...,L−1}×{0,...,L−1}的整数,表示骑士在棋盘上的起始位置和结束位置。假设这些位置是该棋盘上的有效位置。
输出:对于每个测试用例,都单行输出骑士从起点移动到终点所需的最少移动次数。如果起点和终点相等,则移动次数为零。
#include<iostream>
#include<queue>
#include <cstring>
using namespace std;
struct point{//到达的点和需要的步数
int x,y;
int step;
};
int num,sx,sy,ex,ey,tx,ty,L;
const int dx[8] = {-2,-2,-1,-1,1,1,2,2};
const int dy[8] = {1,-1,2,-2,2,-2,1,-1};
int bfs(void);
int main()
{
(cin >> num).get();
int *ps = new int [10];
for (int i = 0; i < num; ++i) {
(cin >> L).get();
(cin >> sx >> sy).get();
(cin >> ex >> ey).get();
ps[i] = bfs();
}
for (int i = 0; i < num; ++i) {
cout << ps[i] << endl;
}
delete [] ps;
return 0;
}
int bfs(void){
if(sx == ex && sy == ey){
return 0;
}
bool vis[L+1][L+1];
memset(vis,false,sizeof(vis));//初始化
queue<point> Q;//定义一个队列
point start,node;
start.x = sx;
start.y = sy;
start.step = 0;//队列初始化
Q.push(start);//压进队列
int step,x,y;
while(!Q.empty()){
start = Q.front(),Q.pop();//取队列的头元素,同时把这个元素弹出
x = start.x;
y = start.y;
step = start.step;//把队列头元素的x、y、step取出
for (int i = 0; i < 8; i++) {//扩展
tx = x+dx[i];
ty = y+dy[i];
if(tx == ex && ty == ey){
return step+1;
}
if(tx>=0 && tx<L && ty>=0 && ty<L && !vis[tx][ty]){
node.x = tx;
node.y = ty;
node.step = step+1;
Q.push(node);//满足条件的进队列
vis[tx][ty] = true;
}
}
}
}
输入:
3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1
输出:
5
28
0