ZOJ 1649

题目链接: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;
}

你可能感兴趣的:(ZOJ,bfs)