hdu1242 Rescue(BFS +优先队列 or BFS )

题意:
Angel被传说中神秘的邪恶的Moligpy人抓住了!他被关在一个迷宫中。迷宫的长、宽不超过200。 迷宫中有不可以越过的墙以及监狱的看守。
Angel的朋友带了一些救援队来到了迷宫中。他们的任务是:接近Angel。我们假设接近Angel就是到达Angel所在的位置。

假设移动需要1单位时间,杀死一个看守也需要1单位时间。到达一个格子以后,如果该格子有看守,则一定要杀死。交给你的任务是,最少要多少单位时间,才能到达Angel所在的地方?(只能向上、下、左、右4个方向移动)

Input

该题含有多组测试数据。每组测试数据第一行二个整数n,m。表示迷宫的大小为n*m (N, M <= 200) 。 以后n行,每行m个时字符。其中“#”代表墙,“.”表示可以移动,“x”表示看守,“a”表示Angel,“r”表示救援队伍。字母均为小写。

Output

一行,代表救出Angel的最短时间。如果救援小组永远不能达到Angel处,则输出“Poor ANGEL has to stay in the prison all his life.”

Sample Input
7 8

.#####.

.a#..r.

..#x…

..#..#.#

…##..

.#……
……..

Sample Output
13

分析:

(N, M <= 200)  首先想到的是BFS, {P.S 有人dfs  0MS AC~~}

 可能有多个’r’,而’a’只有一个,从’a’开始搜,找到的第一个’r’即为所求。

  由于题目中增加了“x”表示看守这一个东东,经过“x”需要多耗一个单位时间。因此如果我们采用普通的宽搜,在第k层搜到了目标,但是耗时可能不止k个单位时间{有可能这条路径经过了“x”}。




对此我有三个想法:

1、采用优先队列(按到达该点的时候),这样就能保证最先扩展到目标状态的时候,耗时是最小的。

2、把当扩展到“x”点时,把他放到与他耗时一样的那一层。这样也能保证到扩展到目标状态时,耗时是最小的。

case1:

#include   
#include   
#include   
#include   
using namespace std; 

int n, m; 
char map[205][205]; 
int sx, sy; 
bool flag; 
struct node { 
    int x, y, step; 
    bool operator <(const node & t) const
    { 
        return step>t.step; 
    } 
}; 
int dx[]= {-1,0,0,1}; 
int dy[]= {0,-1,1,0}; 

void bfs() { 
    node now, tmp; 
    int i,xx,yy; 
    priority_queue q; 
    now.x = sx, now.y = sy, now.step = 0; 
    map[sx][sy] = '#'; 
    q.push(now); 
    while(!q.empty()) { 
        now = q.top(); 
        q.pop(); 
//         cout<
        for(i=0; i<4; i++) { 
            xx = now.x +dx[i]; 
            yy = now.y +dy[i]; 
            if(xx<0||xx>=n||yy<0||yy>=m||map[xx][yy]=='#') continue; 
            if(map[xx][yy]=='r') { 
                cout<1<true; 
                return ; 
            } 
            if(map[xx][yy]=='x') { 
                tmp.x =xx, tmp.y = yy, tmp.step = now.step+2; 
                q.push(tmp); 
            } else { 
                tmp.x =xx, tmp.y = yy, tmp.step = now.step+1; 
                q.push(tmp); 
            } 
            map[xx][yy] = '#'; 
        } 
    } 
} 

int main() { 
    int i, j; 
    while(~scanf("%d%d",&n,&m)) { 
        for(i=0; ifor(j=0; jcin>>map[i][j]; 
                if(map[i][j]=='a') 
                    sx=i,sy=j; 
            } 
        flag = false; 
        bfs(); 
        if(!flag) printf("Poor ANGEL has to stay in the prison all his life.\n"); 
    } 
    return 0; 
} 

case2:

#include   
#include   
#include   
using namespace std; 
struct node 
{ 
    int x, y; 
    int step; 
}; 
queue q; 
int N, M, prove, sx, sy, visit[202][202]; 
char map[202][202]; 
int dx[4] = {-1, 1, 0, 0}; 
int dy[4] = {0, 0, 1, -1,}; 
int check(int x, int y) 
{ 
    if(x < 0 || x >= N || y < 0 || y >= M) 
        return 0; 
    else
        return 1; 
} 
void BFS() 
{ 
    while(!q.empty()) 
        q.pop(); 
    node s, e; 
    memset(visit, 0, sizeof(visit)); 
    s.step = 0;  s.x = sx;  s.y = sy; 
    q.push(s); 
    visit[s.x][s.y] = 1; 
    while(!q.empty()) 
    { 
        s = q.front(); 
        q.pop(); 
        if(map[s.x][s.y] == 'r') 
        { 
            cout << s.step << endl; 
            prove =1; 
        } 
   //如取出的是在有警卫的格子中,即杀掉警卫再次进入队列  
        if(map[s.x][s.y] == 'x')  
        { 
            map[s.x][s.y] = '.'; 
            s.step += 1; 
            q.push(s); 
            continue; 
        } 
        for(int i = 0; i < 4; i++) 
        { 
            e.x = s.x + dx[i];  e.y = s.y + dy[i]; 
            if(!check(e.x, e.y) || visit[e.x][e.y]  
            || map[e.x][e.y] == '#') 
                continue; 
    e.step = s.step + 1; 
            q.push(e); 
            visit[e.x][e.y] = 1; 

   } 
    } 
} 
int main() 
{ 
    while(cin >> N >> M) 
    { 
        for(int i = 0; i < N; i++) 
        for(int j = 0; j < M; j++) 
        {     
            cin >> map[i][j]; 
            if(map[i][j] == 'a') 
            { sx = i;  sy = j; } 
        } 
        prove = 0; 
        BFS(); 
        if(!prove) 
            cout << "Poor ANGEL has to stay in the prison all his life." << endl; 
    } 
    return 0; 
} 

你可能感兴趣的:(搜索)