杭电 HDU ACM 1046 Tempter of the Bone

Tempter of the Bone

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 83458    Accepted Submission(s): 22740


Problem Description
The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.

The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.
 

Input
The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:

'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.

The input is terminated with three 0's. This test case is not to be processed.
 

Output
For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.
 

Sample Input
  
  
4 4 5 S.X. ..X. ..XD .... 3 4 5 S.X. ..X. ...D 0 0 0
 

Sample Output
  
  
NO YES
 

Author
ZHANG, Zheng
 
 
哈哈  ,太爽了~  ,这是acm生涯中做的第一个深度优先搜索 + 奇偶性剪枝问题!  妙极了!~  唉 毕竟第一个学习例题还是看着答案做的 呵呵呵呵, 深刻感受到。dfs的强大啊!!并且 按照自己目前的理解,详细写了注释。专业术语水平表达不够啊,今天刚看了《算法导论》上有关深搜的讲解,还有很多貌似很深的东西都还没看呢~~加油!
明天省赛训练……
 
摘自“杭电 刘春英课件”:

                  深度优先搜索

基本思想:从初始状态S开始,利用规则生成搜索树下一层任一个结点,检查是否出现目标状态G,若未出现,以此状态利用规则生成再下一层任一个结点,再检查是否为目标节点G,若未出现,继续以上操作过程,一直进行到叶节点(即不能再生成新状态节点),当它仍不是目标状态G时,回溯到上一层结果,取另一可能扩展搜索的分支。生成新状态节点。若仍不是目标状态,就按该分支一直扩展到叶节点,若仍不是目标,采用相同的回溯办法回退到上层节点,扩展可能的分支生成新状态,,一直进行下去,直到找到目标状态G为止。

#include<iostream>
#include<cmath>
using namespace std;
char Map[9][9];
int n,m,time,di,dj,si,sj;
bool escape;
int dir[4][2]= {{0,-1},{0,1},{1,0},{-1,0}}; //当时看人家答案都没有看懂这句,也算学习了,意思是用一个数组指定了四个方向。

void dfs(int si,int sj,int t)
{
    if(si>n||sj>m||si<=0||sj<=0)//如果搜索过程中,超出边界那么结束这条路径的搜索,返回上个根节点的邻接表的异于这个结点的结点
        return ;
    if(time==t&&si==di&&sj==dj)//如果搜索过程中发现任何一条满足条件的路径,即可标志 存在性
        escape=1;
    if(escape)
        return ;
    int  temp=(time-t)-abs(si-di)-abs(sj-dj);//这个语句 又包含了两个剪枝的地方,其一:如果某条搜索路径到达某结点后距规定时间的剩余时间已经
    if(time-t<0||temp&1)  //小于此节点到终点的最短所需时间,那么也应该和这次搜索说拜拜。其二:就是奇偶性剪枝,注意到同奇或同偶相减结果
        return ;               //为偶数,否则奇数。
    for(int i=0; i<4; i++) // 对于每个根节点四个方向搜索
    {
        if(Map[si+dir[i][0]][sj+dir[i][1]]!='X') //如果此节点可以走
        {
            Map[si+dir[i][0]][sj+dir[i][1]]='X';//且不能一条路径重复某个结点,所以标记已经走过。
            dfs(si+dir[i][0],sj+dir[i][1],t+1);  //然后再以此为根结点,递归调用,同时t+1路径长度加一
            Map[si+dir[i][0]][sj+dir[i][1]]='.';  //每回溯一条边,把结点标记状态收回,不能影响其他路径经过这个点
        }
    }
    return ;
}

int main()
{
    int i,j;
    while(cin>>n>>m>>time,time+m+n)
    {
        int block=0;
        for(i=1; i<=n; i++)
            for(j=1; j<=m; j++)
            {
                cin>>Map[i][j];
                if(Map[i][j]=='X')
                    block++;
                else if(Map[i][j]=='D')
                {
                    di=i;
                    dj=j;
                }
                else if(Map[i][j]=='S')
                {
                    si=i;
                    sj=j;
                }
            }
        if(n*m-block<time)//也是剪枝,就是能走的路压根就小于时间
        {
            cout<<"NO"<<endl;
            continue;
        }
        escape=0;
        Map[si][sj]='X';
        dfs(si,sj,0);
        if(escape)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值