题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=649
题意:
给一个字符矩阵,‘#’代表墙壁,’.’代表空格,‘x’代表有警察的空格,’r’和’a’分别代表一个主人公,并且’r’要到’a’那里去串门儿,r走一个空格花费单位时间1,走一个有警卫的空格需要先干掉警卫,消耗1单位时间,然后再走过去,也就是共花费时间2,请问r到a那里去最少花费的时间。
思路:
首先要搞明白一个问题:就是路径最短的路不一定花费时间最少。这是可以理解的,比如,一条很短但是有很多警察,另一条路很长,但是没有警察,很有可能是第二条路花费时间少。用深搜?貌似不太合适,因为你一条路径访问过一个点后,另一条路径很可能也会访问这个点,并且时间较少。关键是深搜找到的接不一定是最优的。所以,考虑用广搜解。这道题最朴素的广搜显然不行,也就是说,仅仅求步数最少的不可行,需要加上访问时间这个附加条件。
如果走过一个格子,这个格子存走过时候的时间,下次再走到这个格子,如果时间比格子里的短,就入队,否则,就不用入队了
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <algorithm>
#include <memory.h>
#include <queue>
using namespace std;
int vis[201][201];//存放到达每个点的最优步数
int n,m,t;
int vv[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
char map[201][201];
struct point{
int x,y,step;
}sp;
queue<point>qq;
int ei,ej,minn;
int bfs(point nowp){
qq.push(nowp);//入队
point newp;
int i,j,k;
while(!qq.empty())
{
sp=qq.front();qq.pop();
for(k=0;k<4;k++)
{
i=sp.x+vv[k][0];j =sp.y+vv[k][1];
if(map[i][j]!='#'&&i>=0&&i<n&&j>=0&&j<m)
{
newp.step=sp.step+1;
newp.x=i,newp.y=j;
if(map[i][j]=='x')newp.step++;
if(newp.step<vis[i][j])vis[i][j]=newp.step,qq.push(newp);//更新
}
}
}
return vis[ei][ej];
}
int main(){
while( scanf("%d %d",&n,&m)!=EOF)
{
minn=1000000;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
cin>>map[i][j];
if(map[i][j]=='r')sp.x=i,sp.y=j,sp.step=0;
else if(map[i][j]=='a')ei=i,ej=j;
vis[i][j]=1000000; //初始化
}
vis[sp.x][sp.y]=0;
minn=bfs(sp);
if(minn==1000000)cout<<"Poor ANGEL has to stay in the prison all his life."<<endl;
else cout<<minn<<endl;
}
return 0;
}