本题是多个朋友 "r" 去牢房解救天使 "a" 的故事,"#"是墙,"."是路,路的话走一格需要一步的时间,"x"是守卫,需要先杀死守卫再走过去,耗费两步的时间,问哪一个朋友能在最少步数把天使救出来。
本来很天真,用DFS写了一个,果断TLE了。
后来用BFS写,并且写的时候有一个取巧的地方,就是让天使去寻找朋友,而不是让朋友寻找天使,大概思路是每次把最少步数的节点赋给 节点 t ,然后判断该点是否为 "r",若是,直接break,若否,则把最少步数节点pop出优先队列,然后以 t 为基准向四个方向扩展,直到找出 "r"为止。
先贴一下超时代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
int m, n, min;
int x[4] = {1, 0, -1, 0};
int y[4] = {0, 1, 0, -1};
int sum[201][201];
char s[201][201];
void dfs(int r, int c, int step)
{
if(r < 0 || c < 0 || r >= n || c >= m || step >= sum[r][c])
return;
sum[r][c] = step;
if(s[r][c] == 'r')
{
min = min < step ? min : step;
return;
}
for(int i = 0; i < 4; i++)
{
if(s[r + x[i]][c + y[i]] == '.')
dfs(r + x[i], c + y[i], step + 1);
else if(s[r + x[i]][c + y[i]] == 'x')
dfs(r + x[i], c + y[i], step + 2);
else if(s[r + x[i]][c + y[i]] == 'r')
dfs(r + x[i], c + y[i], step + 1);
}
}
int main(void)
{
int i, j, flag;
while(scanf("%d%d", &n, &m) != EOF)
{
flag = 0;
min = INT_MAX;
memset(sum, 1, sizeof sum);
memset(s, 0, sizeof s);
for(i = 0; i < n; i++)
scanf("%s", s[i]);
for(i = 0; i < n; i++)
{
for(j = 0; j < m; j++)
{
if(s[i][j] == 'a')
{
dfs(i, j, 0);
flag = 1;
break;
}
}
if(flag)
break;
}
if(min == INT_MAX)
printf("Poor ANGEL has to stay in the prison all his life.\n");
else
printf("%d\n", min);
}
}
</pre><p></p><p><span style="font-family:Microsoft YaHei;font-size:18px;">AC代码:</span></p><p><span style="font-family:Microsoft YaHei;font-size:18px;"></span><pre class="cpp" name="code">#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
int x, y, step;
friend bool operator < (node a, node b)
{
return a.step > b.step;
}
};
int main(void)
{
int i, j, n, m, min, flag;
int b[201][201];//标记是否已搜索过
int r[4] = {1, 0, -1, 0};//行方向
int c[4] = {0, 1, 0, -1};//列方向
char s[201][201];
node t, tt;
while(scanf("%d%d", &n, &m) != EOF)
{
flag = 0;
memset(b, 0, sizeof b);
for(i = 0; i < n; i++)
{
scanf("%s", s[i]);
for(j = 0; j < m; j++)
{
if(s[i][j] == 'a')
{
t.x = i;
t.y = j;
b[t.x][t.y] = 1;
t.step = 0;
}
}
}
priority_queue<node> q;//步数小的优先级高,在队列顶端
q.push(t);
while(!q.empty())
{
t = q.top();
if(s[t.x][t.y] == 'r')
{
flag = 1;
min = t.step;
break;
}
q.pop();//一定要把步数最少元素弹出,否则搜索无法进行
for(i = 0; i < 4; i++)
{
if(t.x+r[i]>=0&&t.x+r[i]<n&&t.y+c[i]>=0&&t.y+c[i]<m&&!b[t.x+r[i]][t.y+c[i]])
{
if(s[t.x + r[i]][t.y + c[i]] == '.')
{
tt.x = t.x + r[i];
tt.y = t.y + c[i];
tt.step = t.step + 1;
q.push(tt);
b[t.x + r[i]][t.y + c[i]] = 1;
}
else if(s[t.x + r[i]][t.y + c[i]] == 'x')
{
tt.x = t.x + r[i];
tt.y = t.y + c[i];
tt.step = t.step + 2;
q.push(tt);
b[t.x + r[i]][t.y + c[i]] = 1;
}
else if(s[t.x + r[i]][t.y + c[i]] == 'r')
{
tt.x = t.x + r[i];
tt.y = t.y + c[i];
tt.step = t.step + 1;
q.push(tt);
b[t.x + r[i]][t.y + c[i]] = 1;
}
}
}
}
if(flag)
printf("%d\n", min);
else
printf("Poor ANGEL has to stay in the prison all his life.\n");
}
}