题目描述
话说,年轻的斯巴达勇士们终于走出迷宫,取得胜利并顺利赶了回来。可是等他们回到斯巴达的时候才发现,雅典人趁他们不在偷袭了城邦,并抓走了他们的爱人。侥幸逃出来的几个人说,她们被关押在一个迷宫的牢房里,并把关押她们的迷宫里的情况告诉了年轻的勇士:迷宫中的”S”点表示迷宫的入口,”T”点表示迷宫中牢房的位置,”.”表示空地,可以通过,”#”表示墙,不能直接通过,”K”表示陷阱,一旦进入就必死无疑。每次只能向上下左右四个方向移动,每移动一个单位距离需要耗费一个单位时间,所有斯巴达勇士的移动速度相同。
又是迷宫!!!这次斯巴达的勇士们彻底愤怒了!What’s more, today is the Magpie Festival!
由于斯巴达的勇士们无比愤怒,而且她们也想尽可能的在今天就能救出他们的爱人。所以当他们在迷宫中遇到墙的阻碍时,也能破墙进入。不过破墙的过程会花费一个单位的时间。现在请你计算一下他们最短需要多少时间才能找到迷宫的牢房。
PS:假设迷宫中每个点可以容纳的人数没有限制,每个斯巴达勇士的行动方向之间没有影响。
输入格式
每组测试数据第一行输入二个数n,m(2=<m<=n<=100)分别代表迷宫的长度和宽度。下面n行每行有m个字符用来表示迷宫地图。
0 0表示输入结束,详细输入格式见样例。
输出
输出一个整数,表示找到迷宫出口的最短时间,每组输出占一行。如不能找到出口输入-1
样例输入
3 4
S#.#
..K.
KKT.
0 0
样例输出
8
STL 中优先队列的使用方法(priority_queu)
优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素。但是它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按照先进先出的原则进行,而是将当前队列中最大的元素出队。这点类似于给队列里的元素进行了由大互小的顺序排序。元素的比较规则默认按元素值由大到小排序,可以重载“<”操作符来重新定义比较规则。
基本操作:
empty() 如果队列为空返回真
pop() 删除对顶元素
push() 加入一个元素
size() 返回优先队列中拥有的元素个数
top() 返回优先队列对顶元素
在默认的优先队列中,优先级高的先出队。在默认的int型中先出队的为较大的数。
使用方法:
头文件:
#include <queue>
声明方式:
1、普通方法:
priority_queue<int>q; //通过操作,按照元素从大到小的顺序出队
priority_queue<int,vector<int>, greater<int> >q; //通过操作,按照元素从小到大的顺序出队
2、自定义优先级:
struct cmp {
operator bool ()(int x, int y)
{
return x > y; // x小的优先级高 //也可以写成其他方式,如: return p[x] > p[y];表示p[i]小的优先级高
}
};
priority_queue<int, vector<int>, cmp>q; //定义方法
//其中,第二个参数为容器类型。第三个参数为比较函数。
3、结构体声明方式:
struct node {
int x, y;
friend bool operator < (node a, node b)
{
return a.x > b.x; //结构体中,x小的优先级高
}
};
priority_queue<node>q; //定义方法
//在该结构中,y为值, x为优先级。
//通过自定义operator<操作符来比较元素中的优先级。
//在重载”<”时,最好不要重载”>”,可能会发生编译错误
内容来自:https://www.cnblogs.com/yaoyueduzhen/p/4456430.html
原来的迷宫bfs 先让最近一圈(1)的入列,再从第一个入列的最近一圈找点入列,再在(1)最近一圈找点入列。
而这道题涉及到了不同的权值,什么意思?原来的题(比如古希腊之争(一))的每个点的前进都是1个权值,所有前进的点的权值是一样的,随意的入队出队顺序不会影响。而这题有了破墙,也就是有的点前进权值是2,有的点前进权值是1,在这样的入列出列中找到去终点的权值最小的一条。所以我们要通过一定的手段去调整入队出队的顺序。
举例子图:
然后我们用代码来实现:优先队列的重载我们看上面的知识点 一些需要注意的地方看的代码注释
其中bfs的最后需要是return-1,不然的话在这个代码中刚开始初始化为0,再用now.t去更新,如果找不到出口的话不能输出-1。 并且如果起点终点重合的话直接输出初始化的0就可以了
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
char a[100][100];
int vis[100][100];
int sx,sy,fx,fy;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int n,m;
struct node{
int x;
int y;
int t; //t记录步数
friend bool operator <(node c,node d) ///重载时最好用<
{
return c.t>d.t; 如果a.t>b.t 则认为a<b
}
};
int bfs()
{
priority_queue<node>que;
node now,next;
now.x=sx,now.y=sy,now.t=0;
que.push(now);
vis[sx][sy]=0;
while(que.size())
{
now=que.top();que.pop();
if(now.x==fx&&now.y==fy)
{
return now.t;
}
for(int i=0;i<4;i++)
{
int nx=now.x+dx[i];int ny=now.y+dy[i];
if(nx>=0&&nx<n&&ny>=0&&ny<m&&vis[nx][ny]==-1&&a[nx][ny]!='K')
{
next.x=nx;next.y=ny;
// que.push(next);
vis[nx][ny]=0;
if(a[nx][ny]=='#')
next.t=now.t+2;
if(a[nx][ny]=='.'||a[nx][ny]=='T')
next.t=now.t+1;
que.push(next);///在确定了接下来的步数后再入优先队列
}
}
}
return -1; 如果达不到终点要输出-1
}
int main(void)
{
while(scanf("%d%d", &n, &m)!=EOF)
{
if(n==0&&m==0) break;
memset(vis,-1,sizeof(vis));memset(a,'\0',sizeof(a));
for(int i=0;i<n;i++)
cin>>a[i];
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(a[i][j]=='S')
sx=i,sy=j;
if(a[i][j]=='T')
fx=i,fy=j;
}
}
int res=bfs();
if(res==-1)
printf("-1");
else if(res!=-1)
printf("%d\n",res);
}
return 0;
}