poj 2312 Battle City

来源:互联网 发布:稻谷出糙率计算数据 编辑:程序博客网 时间:2024/04/30 18:37

Description

Many of us had played the game “Battle city” in our childhood, and some people (like me) even often play it on computer now. What we are discussing is a simple edition of this game. Given a map that consists of empty spaces, rivers, steel walls and brick walls only. Your task is to get a bonus as soon as possible suppose that no enemies will disturb you (See the following picture).
这里写图片描述
Your tank can’t move through rivers or walls, but it can destroy brick walls by shooting. A brick wall will be turned into empty spaces when you hit it, however, if your shot hit a steel wall, there will be no damage to the wall. In each of your turns, you can choose to move to a neighboring (4 directions, not 8) empty space, or shoot in one of the four directions without a move. The shot will go ahead in that direction, until it go out of the map or hit a wall. If the shot hits a brick wall, the wall will disappear (i.e., in this turn). Well, given the description of a map, the positions of your tank and the target, how many turns will you take at least to arrive there?

Input

The input consists of several test cases. The first line of each test case contains two integers M and N (2 <= M, N <= 300). Each of the following M lines contains N uppercase letters, each of which is one of ‘Y’ (you), ‘T’ (target), ‘S’ (steel wall), ‘B’ (brick wall), ‘R’ (river) and ‘E’ (empty space). Both ‘Y’ and ‘T’ appear only once. A test case of M = N = 0 indicates the end of input, and should not be processed.

Output

For each test case, please output the turns you take at least in a separate line. If you can’t arrive at the target, output “-1” instead.

Sample Input

3 4
YBEB
EERE
SSTE
0 0

Sample Output

8

Source

POJ Monthly, 鲁小石

声明:以下内容引自“Hackbuteer1的专栏”,对于代码有修改。(因为原来的代码与本人的代码习惯不一样,而且提交到poj上根本Accepted不了23333)

确实是一道非常好的搜索题。对于这道题,通过砖墙时和空地所花的时间不同。通过砖墙时需要耗费2个单位时间。要想用BFS就得改一下,由于BFS每次只能操作一步,要不就是扩展,要不就是破坏砖墙。所以只需检查该点是不是’B’,是的话就得停一步,不是的话,继续扩展,也就是说某些点的扩展慢了一拍,所以从队列里出来的点就判断一下再看执行哪个操作。

方法一:优先队列 + BFS

/*Problem: 2312       User: sarukaMemory: 732K        Time: 47MSLanguage: G++       Result: Accepted*//* 使用STL中的优先队列 */#include<cstdio>#include<queue>#include<cstring>using namespace std;const int maxn = 305;char graph[maxn][maxn];bool vis[maxn][maxn];int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};int m, n, sx, sy;struct node{    int x, y, time;    friend bool operator<(node a, node b)    {        return a.time > b.time;        /* 切记:从小到大排序采用“>”号;如果要从大到小排序,则采用“<”号; */    }};int bfs(){    node you, start, next;    priority_queue<node>q;    you.x = sx;    you.y = sy;    you.time = 0;    q.push(you);    vis[sx][sy] = true;    while(!q.empty())    {        start=q.top();        q.pop();        for(int i = 0; i < 4; i++)        {            next.x = start.x + dir[i][0];            next.y = start.y + dir[i][1];            if(next.x < 0 || next.y < 0 || next.x >= m || next.y >= n || graph[next.x][next.y] == 'R' || graph[next.x][next.y] == 'S' || vis[next.x][next.y])                continue;            if(graph[next.x][next.y] == 'B')                next.time = start.time + 2;            else                next.time=start.time + 1;            if(graph[next.x][next.y] == 'T')                return next.time;            vis[next.x][next.y] = true;            q.push(next);        }    }    return -1;}int main(){    while(scanf("%d%d", &m, &n) == 2)    {        if(m == 0 && n == 0) break;        memset(vis, 0, sizeof(vis));        for(int i = 0; i < m; i++)        {            getchar();            for(int j = 0; j < n; j++)            {                scanf("%c", &graph[i][j]);                if(graph[i][j] == 'Y')                {                    sx = i;                    sy = j;                }            }        }        printf("%d\n", bfs());    }    return 0;}

方法二:记忆化搜索

和优先队列BFS在出队时做处理不同的是,记忆化广搜是在点入队是做处理。记忆化广搜时不必要对点进行标记,只是在入队是注意选择。比如若搜到A点时,要选择比A点时间值大的邻接点入队(不能相等),并更新入队点的时间值。

/*Problem: 2312       User: sarukaMemory: 1104K       Time: 32MSLanguage: G++       Result: Accepted*//* 记忆化搜索 */#include<cstdio>#include<cstring>#include<queue>using namespace std;const int maxn = 305;const int INF = 1009999999;int co, ro, mi;int step[maxn][maxn];char graph[maxn][maxn];bool vis[maxn][maxn];int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};typedef struct node{    int x, y, time;}node;bool judge(int x, int y){    if(x < 0 || y < 0 || x >= co || y >= ro)    {        return false;    }    if(graph[x][y] == 'S'|| graph[x][y] == 'R')    {        return false;    }    return true;}void bfs(int a, int b){    int x, y, ti;    node in, out;    queue<node>que;    in.x = a;    in.y = b;    step[a][b] = 0;    que.push(in);    while(!que.empty())    {        out = que.front();        que.pop();        vis[out.x][out.y] = false;           for(int i = 0; i < 4; i++)        {            x = out.x + dir[i][0];            y = out.y + dir[i][1];            if(!judge(x,y)) continue;            ti = step[out.x][out.y] + 1;            if(graph[x][y] == 'B') ti++;            if(step[x][y] <= ti) continue;            step[x][y] = ti;            if(vis[x][y]) continue;            vis[x][y] = true;            in.x = x;            in.y = y;            que.push(in);        }    }}int main(){    int a, b, c, d;    while(scanf("%d%d", &co, &ro) == 2 && co + ro)    {        getchar();        for(int i = 0; i < co; i++) gets(graph[i]);        for(int i = 0; i < co; i++)        {            for(int j = 0; j < ro; j++)            {                if(graph[i][j] == 'Y')                {                    a = i;                    b = j;                }                if(graph[i][j] == 'T')                {                    c = i;                    d = j;                }                step[i][j] = INF;                   }        }        memset(vis, 0, sizeof(vis));            vis[a][b] = true;            bfs(a, b);            if(step[c][d] != INF)                printf("%d\n", step[c][d]);            else                printf("-1\n");    }    return 0;}

Powered By Saruka.
Copyright © 2016 All Rights Reserved.

0 0
原创粉丝点击