STL工具:优先队列queue
#include <queue>
queue <数据类型>变量名;
queue <pair<int,int> >q;//数据类型为pair
q1 = q.front(); // 将队头元素给q1
q.pop(); //弹出队头元素
q.push(q1); //将q1入队
q.push(make_pair(v,u)); //当数据类型为pair时
q.empty();// 当队列为空时返回true,非空false
题一:P1135 奇怪的电梯
题干简述:每层都有一个数字,选择向上或者向下,不能超过最高楼层也不能低于1层
输入:总层数N 起始楼层数A 目标楼层数B
每层的数字
输出:从A到达B最少需要按多少次电梯
分析:
使用pair数据类型,first记录当前层数,second记录到达当前层数按了多少次电梯
使用优先队列存放元素,每次考虑两种情况:上楼到达的层数,下楼到达的层数;将到达的层数放入优先队列
更新:向上/向下:将向上/向下后的楼层数存入q1,并加上操作次数q1(当前层数,操作次数)将q1入队
//获取上升能到达的楼层
temp=q2.first+num[q2.first];
//若可以上升且未访问过
if(temp<=n&&!mark[temp]){
q1.first=temp;
q1.second=q2.second+1;
q.push(q1);
mark[temp]=true;
}
//获取向下的楼层
temp=q2.first-num[q2.first];
if(temp>=1&&!mark[temp]){
q1.first=temp;
q1.second=q2.second+1;
q.push(q1);
mark[temp]=true;
}
从队列中取出元素q2,判断所在楼层数,如果符合目标楼层则结束,如果不符合则进行向上或者向下操作:以q1作为中间变量进行存取参考步骤3;
#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
int num[210];//记录每层的上下数
bool mark[210];//标记是否走过
queue <pair<int,int> > q;//当前的楼层编号 到达该层所按的次数
pair<int,int> q1,q2;
int main(){
int n,a,b;
int temp=0;
cin>>n>>a>>b;
for(int i=1;i<=n;i++) cin>>num[i];
q1.first=a;q1.second=0;//初始状态
q.push(q1);//将初始状态入队
mark[1]=true;//初始状态标记
while(!q.empty()){
//q2作为队头指针,将队头元素出队
q2=q.front();q.pop();
//当当前楼层为目标楼层时 则结束
if(q2.first==b)break;
//每次都将其上下都入队
//获取上升能到达的楼层
temp=q2.first+num[q2.first];
//若可以上升且未访问过
if(temp<=n&&!mark[temp]){
q1.first=temp;
q1.second=q2.second+1;
q.push(q1);
mark[temp]=true;
}
//获取向下的楼层
temp=q2.first-num[q2.first];
if(temp>=1&&!mark[temp]){
q1.first=temp;
q1.second=q2.second+1;
q.push(q1);
mark[temp]=true;
}
}
if(q2.first==b)cout<<q2.second;
else cout<<-1;
return 0;
}
题二:P1443 马的遍历
题干:有一个 n×m 的棋盘,在某个点 (x, y)上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入:n m x y;
输出:一个n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 -1)。
分析:
使用两个方向矩阵,用一个循环来对马进行操作,一共有八个方向,当符合条件时就将其放入优先队列且更新走到的位置所需要的步数;条件:该点没有走过||不超出边界
#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
//用横纵坐标组成八个方向
const int dx[8]={-1,-2,-2,-1,1,2,2,1};
const int dy[8]={2,1,-1,-2,2,1,-1,-2};
queue<pair<int,int> > q;//构成坐标
int dis[500][500];//存入每个坐标的步数
bool vis[500][500];//对位置进行标记
int main(){
int n,m,x,y;
memset(dis,-1,sizeof(dis));//将所有步数初始化-1
cin>>n>>m>>x>>y;
//将起始点初始化为0 标记
dis[x][y]=0;vis[x][y]=true;
//将点入队
q.push(make_pair(x,y));
//当队列不为空的时候
while(!q.empty()){
//取队头 将其出队
int headx=q.front().first;//设一个队头指针
int heady=q.front().second;
q.pop();
//得到队头坐标,往八个方向进行走
for(int i=0;i<8;i++){
int u=headx+dx[i];
int v=heady+dy[i];
//判定 当超出边界或者已经走过了就跳过
if(u<1 || u>n ||v<1 ||v>m || vis[u][v])
continue;
//符合条件的话
vis[u][v]=true;
q.push(make_pair(u,v));
dis[u][v]=dis[headx][heady]+1;//从原本的位置多走一步
}
}
//将棋盘打印出来
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
printf("%-5d",dis[i][j]);
printf("\n");
}
return 0;
}