zoukankan      html  css  js  c++  java
  • hdu 1010 Tempter of the Bone(dfs)

    Tempter of the Bone

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)


    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
     
    题目大意:
          输入一个n*m的迷宫,和一个时间t(代表可以在迷宫中生存的最长时间,可以理解为超过时间t迷宫将会坍塌,人也会死亡),
          迷宫有一个出口,这个出口只会在第t秒的时候打开,并且人每走一步,走过的道路就会坍塌,迷宫中还有一些墙,人是不能通过的。
          问:一个人从起始地点能否刚好在第t秒的时候到达出口。
     
    解题思路:
          总体思路为 dfs+剪枝  因为最后问能否刚好在第t秒到达出口,所以需要搜索所有能够走的路程,寻找是否有满足条件的情况。
          但是深搜特别费时间,直接暴力搜索一定是会超时的,所以需要通过剪枝来缩短搜索的时间。
     
          首先想到的第一个剪枝是:当剩余的最小步数 > 剩余的时间时 最后是无法在第t秒到达出口的。
          接下来需要用到的一个剪枝为:奇偶剪枝
     
    奇偶剪枝:
          我们可以定义一个map数组来表示每个点的奇偶性(每个点的奇偶性为该点横纵坐标的和)
          0 1 0 1 0 1 
          1 0 1 0 1 0 
          0 1 0 1 0 1 
          1 0 1 0 1 0 
          0 1 0 1 0 1 
          有这个表可以发现 从为0的格子走一步,必然走向为1的格子;同样从为1的格子走一步,必然走向为0的格子.
          即 0-->1或1-->0 必然是奇数步       0-->0或1-->1 必然是偶数步 
          so~ 当遇到从0走到0但是要求奇数步、或者从1走到0但是要求偶数步,都可以之间判断不能到达。
          应用到这个题上就是:判断剩余时间和剩余的最小步数的奇偶性是否相同。相同则有可能到达、不同则一定不能到达。
          (奇数-偶数 = 奇数    奇数-奇数= 偶数    偶数-偶数=偶数)
     
    AC代码:
     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <stdlib.h>
     4 #include <string.h>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 char p[10][10];
     9 int a[4][2] = {-1,0,0,1,1,0,0,-1};  // 方向数组
    10 int flag;  // 标记是否能够在第t秒时到达出口
    11 int n,m,t;
    12 int sx,sy,dx,dy;  // 起始地点  和  出口的地点
    13 
    14 void dfs(int x,int y,int k)
    15 {
    16     int i;
    17     if (x<1 || y<1 || x>n || y>m)   // 判断是否超出边界
    18         return ;
    19     if (k == 0&&x == dx && y==dy)   // 如果刚好在第t秒时到达出口  flag = 1
    20     {
    21         flag = 1;
    22         return ;
    23     }
    24     int tmp = k - abs(x-dx)-abs(y-dy);   
    25     if (tmp < 0 || tmp&1)   //  判断 1、是否剩余的最小步数 > 剩余的时间 2、剩余时间和剩余的最小步数的奇偶性是否相同
    26         return ;
    27 
    28     for (i = 0; i < 4; i ++)
    29     {
    30         if (p[x+a[i][0]][y+a[i][1]] != 'X')  // 如果时墙则不能通过
    31         {
    32             p[x+a[i][0]][y+a[i][1]] = 'X';   // 走过之后路就坍塌了(之后不能在通过)
    33             dfs(x+a[i][0],y+a[i][1],k-1);
    34             if (flag) return ;     // 如果满足条件直接退出
    35             p[x+a[i][0]][y+a[i][1]] = '.';   // 当前搜的这条路可能不满足条件  下次再搜别的路时要恢复原样
    36         }
    37     }
    38     return ;
    39 }
    40 int main ()
    41 {
    42     int i,j;
    43     while (scanf("%d%d%d",&n,&m,&t)!=EOF)
    44     {
    45         getchar();
    46         int sum = 0;
    47         if (n==0&&m==0&&t==0)
    48             break;
    49         for (i = 1; i <= n; i ++)
    50         {
    51             for (j = 1; j <= m; j ++)
    52             {
    53                 scanf("%c",&p[i][j]);
    54                 if (p[i][j] == 'S'){sx = i; sy = j;}
    55                 else if (p[i][j] == 'D'){dx = i; dy = j;}
    56                 else if (p[i][j] == 'X') sum ++;
    57             }
    58             getchar();
    59         }
    60 
    61         if (n*m-sum <= t)    // 如果可以走的路的步数小于t 直接pass
    62         {
    63             printf("NO
    ");
    64             continue;
    65         }
    66         p[sx][sy] = 'X';  // 出发之后不能再回到起点
    67         flag = 0;
    68         dfs(sx,sy,t);
    69         if (flag)
    70             printf("YES
    ");
    71         else
    72             printf("NO
    ");
    73     }
    74     return 0;
    75 }     
     
  • 相关阅读:
    jenkins免密添加SSH Servers
    Workman启动失败的解决方法 stream_socket_server() has been disabled for security reasons
    jenkins主从从服务器发布脚本执行成功但总提示失败 FATAL: Remote call on XXXX failed
    mac OS配置用户全局环境变量(设置字符集为UTF8)
    使用 Application Loader提交IPA文件到苹果市场
    IOS使用批处理打包
    Java进阶知识24 Spring对JDBC的支持
    Java进阶知识23 Spring execution 切入点表达式
    Java进阶知识22 Spring的AOP编程
    Java进阶知识21 Spring的代理模式
  • 原文地址:https://www.cnblogs.com/yoke/p/6740751.html
Copyright © 2011-2022 走看看