【ZOJ1649 Rescue】 解题报告+代码+思路

7 篇文章 0 订阅
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
//#define INPUT
using namespace std;
/**
    Problem : ZOJ1649 - Rescue
    Begin Time : 7:00 p.m. 17th/Mar/2012
    End Time : 22:17 17th/Mar/2012
    Knowledge:
        BFS+标记技巧
    Thought:
        其实是反着来搜索的,是点a去找点r们,而不是点r去找点a
        移动按照普通的深搜移动规则就好。
        但是对于每个点是否已经访问过不是像往常那样
        vis[i][j] = 1就完事儿了,我们在_time数组里判断某个点是否已经找过
        换言之,只有当(i,j)访问(i,j+1)的时候,(i,j)到(i,j+1)的代价小于
        原来(i,j+1)的代价才准许访问。
        这点跟那个Nightmare是十分类似的。

        其实也可以用优先队列来做。
    Exp.:
        ZOJ的数据是多组输入的,所以一定要
        while(scanf("%d") != EOF )
*/
struct node
{
    int x;
    int y;
    int _time;
};
const int dx[] = {0,0,-1,1};
const int dy[] = {1,-1,0,0};
char maze[210][210];
int _time[210][210];
node que[1000000];

int startx,starty;
bool check(node tmp,int N,int M)
{
    if ( tmp.x >= N || tmp.x < 0
            || tmp.y >= M || tmp.y < 0
            || maze[tmp.x][tmp.y] == '#'
            ||
            (_time[tmp.x][tmp.y] != 0 && _time[tmp.x][tmp.y] < tmp._time )
       )
        return false;
    return true;
}
void Solve(int N,int M)
{
    bool isFound =false;
    int front = 1, rear = 2;
    int btime = 1000000;
    node tmp,tmp1;
    tmp.x = startx;
    tmp.y = starty;
    tmp._time = 0;
    que[front] = tmp;
    while( front < rear )
    {
        tmp = que[front];
        _time[tmp.x][tmp.y] = tmp._time;
        if( maze[tmp.x][tmp.y] == 'r' )
        {
            ///找到朋友们
            isFound = true;
            if ( _time[tmp.x][tmp.y] < btime )
                btime = _time[tmp.x][tmp.y];
        }
        ///为某个点打上时间标记。

        for(int i = 0 ; i < 4 ; i++)
        {
            tmp1.x = tmp.x + dx[i];
            tmp1.y = tmp.y + dy[i];
            if( tmp1.x < N && tmp1.x >= 0
                    && tmp1.y < M && tmp1.y >= 0)
            {
                if( maze[tmp1.x][tmp1.y] == 'x')
                    tmp1._time = tmp._time + 2;
                else
                    tmp1._time = tmp._time + 1;
                if( check(tmp1,N,M) )
                {
                    que[rear++] = tmp1;
                }
            }

        }
        front++;
    }
    if( isFound )
    {
        printf("%d\n",btime);
    }
    else
    {
        printf("Poor ANGEL has to stay in the prison all his life.\n");
    }
}
int main()
{
    int n,m;
    node tp;
    char t[5];
#ifdef INPUT
    freopen("b:\\acm\\zoj1649\\input.txt","r",stdin);
#endif
    while ( scanf("%d%d",&n,&m) != EOF )
    {
        memset(maze,0,sizeof(maze));
        memset(_time,0,sizeof(_time));
        memset(que,0,sizeof(que));
        gets(t);
        for(int i = 0 ; i < n ; i++)
        {
            gets(maze[i]);
            //  gets(t);
            for ( int j = 0 ; j <m ; j++)
            {
                if( maze[i][j] == 'a' )
                {
                    startx = i;
                    starty = j;
                }
            }
        }
        Solve(n,m);
    }

    // cout << "Hello world!" << endl;
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值