题意:
n*m的方格中,'#/是墙不可过,'.'是路可过,a代表要救出的
公主,r是出发的friend,x代表守卫,每走一步都需要一单位
的时间,遇到守卫需要额外再消耗一单位的时间,求从r走到a
最短需多少的时间。
分析:
1,要注意从a开始搜索,因为r可能含有多个。开始我是从r搜索到a,
后来wa了很多次。。。最后发现题目中说的是friends,,,是个复数。。
so。。。该从a搜到r后就ac了。。。
2.搜过的路要做标记,标记完了不用取消标记,这一点和dfs不同,dfs是标记->dfs->取消标记
这道题求最短时间,应该用bfs+优先队列做,这样搜索到的时间最小。
注意标记走过的点,定义优先队列的时候,需要重载运算符<,详见代码。
//没学c++,重载看不懂。。。伤不起。。orz
//代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
struct node
{
int x,y;
int ans;
bool operator <(const node t)const
{
return ans > t.ans;//从小到大排序
}
};
const int maxn = 205;
char grid[maxn][maxn];
int n,m,ax,ay,rx,ry;
int dx[4]= {-1,0,0,1},dy[4]= {0,1,-1,0};
int vis[300][300];
void bfs(int x, int y)
{
memset(vis,0,sizeof(vis));
priority_queue<node>q;
node f1, f2;
f1.x=x;
f1.y=y;
f1.ans=0;
q.push(f1);
vis[x][y]=1;
while(!q.empty())
{
f1=q.top();
q.pop();
if(grid[f1.x][f1.y]=='r')
{
printf("%d\n",f1.ans);
return ;
}
for(int i=0; i<4; i++)
{
f2.x=f1.x+dx[i];
f2.y=f1.y+dy[i];
if(f2.x>=0&&f2.x<n&&f2.y>=0&&f2.y<m&&!vis[f2.x][f2.y]&&grid[f2.x][f2.y]!='#')
{
vis[f2.x][f2.y]=1;//搜过的路要做标记,这一点和dfs不同,dfs是 标记->dfs->取消标记
if(grid[f2.x][f2.y]=='x')//分2种情况,如果是守卫的话就加2
{
f2.ans=f1.ans+2;
}
else//否则就是普通的路,加1
{
f2.ans=f1.ans+1;
}
q.push(f2);
}
}
}
printf("Poor ANGEL has to stay in the prison all his life.\n");
}
int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
int i,j;
for(i=0; i<n; i++)
{
getchar();
for(j=0; j<m; j++)
{
scanf("%c",&grid[i][j]);
if(grid[i][j]=='a')
{
ax=i;
ay=j;
}
if(grid[i][j]=='r')
{
rx=i;
ry=j;
}
}
}
bfs(ax,ay);
}
return 0;
}