Zoj 2110 Tempter of the Bone

题目描述:
一只小狗在一个古老的迷宫里找到一根骨头,当它叼起骨头时,迷宫开始颤抖,它感觉到地
面开始下沉。它才明白骨头是一个陷阱,它拼命地试着逃出迷宫。
迷宫是一个N×M 大小的长方形,迷宫有一个门。刚开始门是关着的,并且这个门会在第T 秒
钟开启,门只会开启很短的时间(少于一秒),因此小狗必须恰好在第T 秒达到门的位置。每秒钟,
它可以向上、下、左或右移动一步到相邻的方格中。但一旦它移动到相邻的方格,这个方格开始
下沉,而且会在下一秒消失。所以,它不能在一个方格中停留超过一秒,也不能回到经过的方格。
小狗能成功逃离吗?请你帮助他。
输入描述:
输入文件包括多个测试数据。每个测试数据的第一行为三个整数:N M T,(1<N, M<7;
0<T<50),分别代表迷宫的长和宽,以及迷宫的门会在第T 秒时刻开启。
接下来N 行信息给出了迷宫的格局,每行有M 个字符,这些字符可能为如下值之一:
X: 墙壁,小狗不能进入 S: 小狗所处的位置
D: 迷宫的门 . : 空的方格
输入数据以三个0 表示输入数据结束。
输出描述:

对每个测试数据,如果小狗能成功逃离,则输出"YES",否则输出"NO"。


#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
char map[9][9]; //迷宫地图
int n, m, t; //迷宫的大小,及迷宫的门会在第t 秒开启
int di, dj; //(di,dj):门的位置
bool escape; //是否成功逃脱的标志,escape 为1 表示能成功逃脱
int dir[4][2] = { {0,-1}, {0,1}, {1,0}, {-1,0} }; //分别表示下、上、左、右四个方向
//已经到达(si,sj)位置,且已经花费cnt 秒
void dfs( int si, int sj, int cnt )
{
    int i, temp;
    if( si>n || sj>m || si<=0 || sj<=0 ) return; //边界
    if( si==di && sj==dj && cnt==t ) //成功逃脱
    {
        escape = 1;
        return;
    }
//abs(x-ex) + abs(y - ey)表示现在所在的格子到目标格子的距离(不能走对角线)
//t-cnt 是实际还需要的步数,将他们做差
//如果temp < 0 或者temp 为奇数,那就不可能到达!
    temp = (t-cnt) - fabs(si-di) - fabs(sj-dj); //搜索过程当中的剪枝
    if( temp<0 || temp%2 ) return;
    for( i=0; i<4; i++ )
    {
        if( map[ si+dir[i][0] ][ sj+dir[i][1] ] != 'X')
        {
//前进方向!将当前方格设置为墙壁‘X’
            map[ si+dir[i][0] ][ sj+dir[i][1] ] = 'X';
            dfs(si+dir[i][0], sj+dir[i][1], cnt+1); //从下一个位置继续搜索
            if(escape) return;
            map[ si+dir[i][0] ][ sj+dir[i][1] ] = '.'; //后退方向!恢复现场!
        }
    }
    return;
}
int main( )
{
    int i, j; //循环变量
    int si, sj; //小狗的起始位置
    while( scanf("%d%d%d", &n, &m, &t) )
    {
        if( n==0 && m==0 && t==0 ) break; //测试数据结束
        int wall = 0;
        char temp;
        scanf( "%c", &temp ); //见下面的备注
        for( i=1; i<=n; i++ )
        {
            for( j=1; j<=m; j++ )
            {
                scanf( "%c", &map[i][j] );
                if( map[i][j]=='S' )
                {
                    si=i;
                    sj=j;
                }
                else if( map[i][j]=='D' )
                {
                    di=i;
                    dj=j;
                }
                else if( map[i][j]=='X' ) wall++;
            }
            scanf( "%c", &temp );
        }
        if( n*m-wall <= t ) //搜索前的剪枝
        {
            printf( "NO\n" );
            continue;
        }
        escape = 0;
        map[si][sj] = 'X';
        dfs( si, sj, 0 );
        if( escape ) printf( "YES\n" ); //成功逃脱
        else printf( "NO\n" );
    }
    return 0;
}


你可能感兴趣的:(Zoj 2110 Tempter of the Bone)