蒜头君回家

思路

本题思路和考虑方式比较特别,值得分享一下。

根据题意,需要先拿到钥匙再到达终点,求出最少的步数。

个人思路

首先最容易想到的是bfs的层数即为最少步数,但要注意一个易错点(个人思路犯的错误),并不是现在起点找到最近的钥匙,再拿着钥匙去终点,这是典型的贪心思想。这并只能保证拿到钥匙的步数最少,而钥匙与终点之间的距离没有考虑到。

本题思路

应该从全局着手,要知道行走的路程是可逆的,即起点与终点到各个钥匙的路程和各个钥匙回到起点终点的路程可逆,因此分别从起点和终点做一次bfs,把到达各个钥匙所用的步数存储起来,最后找出最小的步数即可

代码

代码有些冗余,主要是不想使用三维数组

#include

using namespace std;

int n, m, minpath = 0x3fffffff;

char mp[2005][2005];

bool inq[2005][2005], reverinq[2005][2005];//正向inq,反向reverinq

int keys[2005][2005];//拿不同钥匙需要走的步数

int dir[4][2] = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};

int sx, sy, ex, ey, cntkeys;

struct Node

{

int x;

int y;

int step;

Node(){}

Node(int xx, int yy, int ss)

{

x = xx;

y = yy;

step = ss;

}

};

queue q, reverq;

//坐标xy

void bfs1(int x, int y)

{

int cnt = 0;

Node node = Node(x, y, 0);

q.push(node);

inq[x][y] = true;

while(!q.empty())

{

Node top = q.front();

q.pop();

if(mp[top.x][top.y] == 'P')

{

cnt++;

keys[top.x][top.y] = top.step;

}

if(cnt == cntkeys)

break;

for(int i = 0; i < 4; i++)

{

int tx = top.x + dir[i][0];

int ty = top.y + dir[i][1];

if(tx >= 0 && tx < n && ty >= 0 && ty < m && mp[tx][ty] != '#' && !inq[tx][ty])

{

inq[tx][ty] = true;

Node temp = Node(tx, ty, top.step + 1);

q.push(temp);

}

}

}

}

void bfs2(int x, int y)

{

int cnt = 0;

Node node = Node(x, y, 0);

reverq.push(node);

reverinq[x][y] = true;

while(!reverq.empty())

{

Node top = reverq.front();

reverq.pop();

if(mp[top.x][top.y] == 'P')

{

cnt++;

keys[top.x][top.y] += top.step;

minpath = min(minpath, keys[top.x][top.y]);

}

if(cnt == cntkeys)

break;

for(int i = 0; i < 4; i++)

{

int tx = top.x + dir[i][0];

int ty = top.y + dir[i][1];

if(tx >= 0 && tx < n && ty >= 0 && ty < m && mp[tx][ty] != '#' && !reverinq[tx][ty])

{

reverinq[tx][ty] = true;

Node temp = Node(tx, ty, top.step + 1);

reverq.push(temp);

}

}

}

}

int main()

{

scanf("%d %d", &n, &m);

for(int i = 0; i < n; i++)

{

for(int j = 0; j < m; j++)

{

scanf(" %c", &mp[i][j]);

if(mp[i][j] == 'S')

{

sx = i;

sy = j;

}

else if(mp[i][j] == 'T')

{

ex = i;

ey = j;

}

else if(mp[i][j] == 'P')

{

cntkeys++;//统计钥匙的个数

}

}

}

bfs1(sx, sy);

bfs2(ex, ey);

printf("%d\n", minpath);

return 0;

}