您的位置:首页 > 其它

计蒜客-蒜头君回家(bfs)

2018-03-06 17:30 302 查看
蒜头君要回家,但是他家的钥匙在他的朋友花椰妹手里,他要先从花椰妹手里取得钥匙才能回到家。花椰妹告诉他:“你家的钥匙被我复制了很多个,分别放在不同的地方。”
蒜头君希望能尽快回到家中,他需要首先取得任意一把钥匙,请你帮他计算出回家所需要的最短路程。
蒜头君生活的城市可以看做是一个 n×m 的网格,其中有道路有障碍,钥匙和家所在的地方可以看做是道路,可以通过。蒜头君可以在城市中沿着上下左右 4 个方向移动,移动一个格子算做走一步。
输入格式
第一行有两个整数 n,m。城市的地图是 n 行 m 列。(1≤n,m≤2000)
接下来的 n 行,每行 m 个字符,代表城市的地图。’.’ 代表道路,’#’ 代表障碍物,’S’ 代表蒜头君所在的位置,’T’ 代表蒜头家的位置,’P’代表钥匙的位置。除了障碍物以外,别的地方都可以通过。(题目保证蒜头君至少有一条路径可以顺利拿到钥匙并且回家)
输出格式
输出蒜头回家要走的最少步数,占一行。
样例输入
8 10
P.####.#P#
..#..#...#
..#T##.#.#
..........
..##.#####
..........
#####...##
###....S##
样例输出
21
解题说明:这里我们并不是先搜索所有钥匙,再从每个每个钥匙出发找终点,这样肯定会超时。
我们就搜一次,真的就一次!搜索的过程中,找到钥匙的,其后面走过的坐标都记标志,标志说明我已经有钥匙了,没有标识,则经过终点也继续搜。记一个flag不行,不同的路径在搜,可能其中一条找到钥匙了,你变了flag,另外的没有钥匙的到了终点判断到了,就错了。
标志的问题,多加一维,已经有钥匙了有没走过,和没有钥匙的走没走过。

ac代码:
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxl 2010
using namespace std;
int n,m;
int a[maxl][maxl],vist[maxl][maxl][2];
int cg[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct point{
int x;int y;int foot;int flag;
point(int xx,int yy,int fot,int f){
x=xx;y=yy;foot=fot;flag=f;
}
};
int bfs(int x,int y){
queue<point>q;
q.push(point(x,y,0,0));
vist[x][y][0]=1;
while(!q.empty()){
point po=q.front();
q.pop();
for(int i=0;i<4;i++){
int tx=po.x+cg[i][0];
int ty=po.y+cg[i][1];
if(a[tx][ty]!='#'&&!vist[tx][ty][po.flag]&&tx>0&&tx<=n&&ty>0&&ty<=m){
vist[tx][ty][po.flag]=1;
if(a[tx][ty]=='P'){
q.push(point(tx,ty,po.foot+1,1));
}
else if(a[tx][ty]=='T'&&po.flag){
return po.foot+1;
}

else q.push(point(tx,ty,po.foot+1,po.flag));
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
memset(vist,0,sizeof(vist));
int bx,by;
for(int i=1;i<=n;i++){
getchar();
for(int j=1;j<=m;j++){
scanf("%c",&a[i][j]);
if(a[i][j]=='S'){
bx=i;by=j;
}
}
}
printf("%d\n",bfs(bx,by));
return 0;
}
运行超时代码:#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<map>
#define maxl 2048
using namespace std;
int n,m,ans=0,flag=0;
int a[maxl][maxl],mark[maxl][maxl];long long b[maxl][maxl];
int cgx[4]={1,-1,0,0};
int cgy[4]={0,0,1,-1};
long long mn=100000000000007;
int ex,ey;
map<int,map<int,int> >mp;
struct point{
int x;int y;
point(int xx,int yy){
x=xx;
y=yy;
}
};
struct p{
int p1;
int p2;
}pz[maxl*maxl];
void bfs(int x,int y,int index){
queue<point>q;
while(!q.empty()){
q.pop();
}
q.push(point(x,y));
mark[x][y]=1;
while(!q.empty()){
if(index==ans)return ;
x=q.front().x;
y=q.front().y;
q.pop();
for(int i=0;i<4;i++){
int tx=x+cgx[i];
int ty=y+cgy[i];
if(a[tx][ty]&&!mark[tx][ty]&&tx>0&&tx<=n&&ty>0&&ty<=m){
mark[tx][ty]=1;
b[tx][ty]=b[x][y]+1;
q.push(point(tx,ty));
if(a[tx][ty]==2&&!flag){
mp[tx][ty]=b[tx][ty];
index++;
}
if(flag&&a[tx][ty]==6){
return ;
}
}
}
}
return ;
}
int main(){
scanf("%d%d",&n,&m);
char ip1;int bx,by;
for(int i=1;i<=n;i++){
string s;cin>>s;
for(int j=1;j<=m;j++){
ip1=s[j-1];
if(ip1=='S'){
a[i][j]=1;
bx=i;by=j;
}
else if(ip1=='.')a[i][j]=1;
else if(ip1=='P'){
pz[ans].p1=i;pz[ans].p2=j;
ans++;
a[i][j]=2;
}
else if(ip1=='T'){
ex=i;ey=j;
a[i][j]=6;
}
else a[i][j]=0;
}
}
bfs(bx,by,0);
for(int i=0;i<ans;i++){
memset(mark,0,sizeof(mark));
memset(b,0,sizeof(b));
if(mp[pz[i].p1][pz[i].p2]){
flag=1;
bfs(pz[i].p1,pz[i].p2,0);
if(b[ex][ey]){
if(mp[pz[i].p1][pz[i].p2]+b[ex][ey]<mn)mn=mp[pz[i].p1][pz[i].p2]+b[ex][ey];
}
}
}
printf("%d\n",mn);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: