链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
给你一个n*m的图,地图上'.'代表可以走的地方,而'#'代表陷阱不能走,
'P'代表人物位置,'K'代表钥匙,'E'代表出口。人物一个,钥匙有多个,
('K'的数量<=50)),出口一个,每个位置可以向(上,下,左,右)四个
方向走一格,花费一个单位时间,现在你需要花费最少的时间拿到钥匙
然后从迷宫的出口出去(若没有钥匙,则不能进入迷宫出口所在的格子)。
输入描述:
第一行一个整数T(T <= 50),代表数据的组数 接下来一行n,m(n<=500,m<=500),代表地图的行和列 接下来n行,每行一个长度为m的字符串,组成一个图。
输出描述:
如果可以出去,输出所花费的最少时间。 如果不能出去,输出一行"No solution"。
示例1
输入
3 5 5 ....P ##..E K#... ##... ..... 5 5 P.... ..... ..E.. ..... ....K 5 5 P#..E .#.#. .#.#. .#.#. ...#K
输出
No solution 12 No solution
分析
第一次错误的代码是先bfs钥匙,找到钥匙再bfs到终点,就是内置bfs,这样子会造成tle
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 600;
bool vis[N][N];
bool vis2[N][N];
char g[N][N];
int dist_key[N][N];
int dist_out[N][N];
typedef pair<int,int> PII;
int t;
int n,m,px,py,ex,ey;
int dist = 0x3f3f3f3f;
int dx[] = {-1,1,0,0},dy[] = {0,0,-1,1};
bool f_key;
bool f_out;
int bfs2(int x,int y)
{
memset(vis2,false,sizeof vis2);
memset(dist_out,0x3f3f3f,sizeof dist_out);
dist_out[x][y] = 0;
queue<PII> q;
q.push({x,y});
vis2[x][y] = true;
while(q.size())
{
PII cur = q.front();
q.pop();
for(int i = 0;i<4;i++)
{
int xx = cur.first + dx[i],yy = cur.second + dy[i];
if(xx>=1 && xx<=n && yy>=1 && yy<=m &&(g[xx][yy] =='.'|| g[xx][yy] == 'E') && !vis2[xx][yy])
{
dist_out[xx][yy] = min(dist_out[xx][yy],dist_out[cur.first][cur.second] +1);
vis2[xx][yy] = true;
q.push({xx,yy});
}
}
}
if(dist_out[ex][ey] == 0x3f3f3f3f) return -1;
else
return dist_out[ex][ey];
}
int bfs(int x,int y)
{
memset(vis,false,sizeof vis);
memset(dist_key,0x3f3f3f,sizeof dist_key);
dist_key[x][y] = 0;
queue<PII> q;
q.push({x,y});
vis[x][y] = true;
while(q.size())
{
PII cur = q.front();
q.pop();
for(int i = 0;i<4;i++)
{
int xx = cur.first + dx[i],yy = cur.second + dy[i];
if(xx>=1 && xx<=n && yy>=1 && yy<=m && (g[xx][yy] =='.'|| g[xx][yy] == 'K') && !vis[xx][yy])
{
vis[xx][yy] = true;
dist_key[xx][yy] = min(dist_key[xx][yy],dist_key[cur.first][cur.second]+1);
q.push({xx,yy});
if(g[xx][yy] == 'K')
{
f_key = true;
int k = bfs2(xx,yy);
if(k != -1)
{
f_out = true;
dist = min(dist,dist_key[xx][yy]+k);
}
}
}
}
}
if(dist == 0x3f3f3f3f)return -1;
else return dist;
}
int main()
{
cin>>t;
while(t--)
{
dist = 0x3f3f3f3f;
f_key = f_out = false;
cin>>n>>m;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=m;j++)
{
cin>>g[i][j];
if(g[i][j] == 'P')
{
px = i,py = j;
}
if(g[i][j] == 'E')
{
ex = i,ey = j;
}
}
}
int r = bfs(px,py);
if(r == -1)cout<<"No solution"<<endl;
else
cout<<r<<endl;
}
return 0;
}
正确的思路应该是分两次bfs,第一次从起点记录钥匙的位置和距离,第二次从终点走,如果走到已经记录过的钥匙,算出距离,求最小值即可
ac代码
#include<bits/stdc++.h>
using namespace std;
const int N = 600;
bool vis[N][N];
bool vis2[N][N];
char g[N][N];
int dist_key[N][N];
int dist_out[N][N];
int sum[N][N];
typedef pair<int,int> PII;
int t;
int n,m,px,py,ex,ey;
int dist = 0x3f3f3f3f;
int dx[] = {-1,1,0,0},dy[] = {0,0,-1,1};
void bfs(int x,int y)
{
memset(vis,false,sizeof vis);
memset(dist_key,0x3f3f3f,sizeof dist_key);
dist_key[x][y] = 0;
queue<PII> q;
q.push({x,y});
vis[x][y] = true;
while(q.size())
{
PII cur = q.front();
q.pop();
for(int i = 0;i<4;i++)
{
int xx = cur.first + dx[i],yy = cur.second + dy[i];
if(xx>=1 && xx<=n && yy>=1 && yy<=m && (g[xx][yy] =='.'|| g[xx][yy] == 'K') && !vis[xx][yy])
{
vis[xx][yy] = true;
dist_key[xx][yy] = min(dist_key[xx][yy],dist_key[cur.first][cur.second]+1);
q.push({xx,yy});
if(g[xx][yy] == 'K')
{
sum[xx][yy]++;
}
}
}
}
}
void bfs2(int x,int y)
{
memset(vis,false,sizeof vis);
memset(dist_out,0x3f3f3f,sizeof dist_out);
dist_out[x][y] = 0;
queue<PII> q;
q.push({x,y});
vis[x][y] = true;
while(q.size())
{
PII cur = q.front();
q.pop();
for(int i = 0;i<4;i++)
{
int xx = cur.first + dx[i],yy = cur.second + dy[i];
if(xx>=1 && xx<=n && yy>=1 && yy<=m && (g[xx][yy] =='.'|| g[xx][yy] == 'K') && !vis[xx][yy])
{
vis[xx][yy] = true;
dist_out[xx][yy] = min(dist_out[xx][yy],dist_out[cur.first][cur.second]+1);
q.push({xx,yy});
if(g[xx][yy] == 'K')
{
if(sum[xx][yy])
{
dist = min(dist,dist_key[xx][yy] + dist_out[xx][yy]);
}
}
}
}
}
}
int main()
{
cin>>t;
while(t--)
{
dist = 0x3f3f3f3f;
cin>>n>>m;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=m;j++)
{
cin>>g[i][j];
if(g[i][j] == 'P')
{
px = i,py = j;
}
if(g[i][j] == 'E')
{
ex = i,ey = j;
}
}
}
bfs(px,py);
bfs2(ex,ey);
if(dist == 0x3f3f3f3f) cout<<"No solution"<<endl;
else
cout<<dist<<endl;
}
return 0;
}