Tempter of the Bone--hdu1010--zoj2110

Tempter of the Bone

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


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
 
 
这个题主要是用深搜,看所有路径中有没有步数为给出的值的!
但是注意只用搜索一定会超时!!!
还要用 奇偶剪枝!
 
 
下面我讲一下奇偶剪枝
    
一起看这个图,要从S到E,如果没有障碍物#,最短的路径是6步!
但是有障碍物之后,我们就要绕路走,这时候的步数可以分为两部分  1.最短路径部分
                               2.走出最短路径的步数加上走回最短路径的步数(注意,走出去和走回的步数是相等的)
 
 
解释一下为什么会相等
 
 
看这个图,最短路径是黑色部分,现在要走红色部分,那么走出和走回最短路径的部分就是红色部分,为什么不算上蓝色的呢,因为如果把红色去掉,蓝色部分平移后就是最短路径!!
所以说,要想t步走到终点,多走的部分一定是偶数     即是(t-最短步数)一定为偶数,所以,我们就能剪枝了!
 
 
 
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 char map[8][8];
 6 int m,n,bx,by,ex,ey,step,t,flag;
 7 int mov[4][2]={0,1,0,-1,1,0,-1,0};
 8 
 9 bool can(int x,int y)
10 {
11     if(x<0||x>m-1||y<0||y>n-1||map[x][y]=='X')
12     return false;
13     return true;
14 }
15 void DFS(int x,int y)
16 {
17 
18     int xx,yy,i;
19     if(x==ex&&y==ey)//判断是否找到终点
20     {
21         if(step==t)
22         flag=1;
23         return ;
24     }
25     if(step>t)
26         return ;
27        int dis=t-abs(ex-x)-abs(ey-y)-step;
28     if(dis<0||dis&1)//奇偶剪枝
29         return ;
30         if(flag==1)
31         return ;//当初我就是没加这一句,在hduoj上超时了,但是在zoj上能过
32     for(i=0;i<4;i++)
33     {
34         xx=x+mov[i][0];
35         yy=y+mov[i][1];
36         if(can(xx,yy))
37         {
38             step++;
39             map[xx][yy]='X';
40             DFS(xx,yy);
41             step--;
42             map[xx][yy]='.';
43         }
44     }
45 }
46 int main()
47 {
48     int i,j;
49     while(scanf("%d%d%d",&m,&n,&t),m||n||t)
50     {
51         getchar();//吸收回车符
52         for(i=0;i<m;i++)
53         {
54             for(j=0;j<n;j++)
55             {
56                 scanf("%c",&map[i][j]);
57                 if(map[i][j]=='S')
58                 {
59                     bx=i;
60                     by=j;
61                 }
62                 if(map[i][j]=='D')
63                 {
64                     ex=i;
65                     ey=j;
66                 }
67             }
68             getchar();
69         }
70         flag=0;
71         step=0;
72         int best=abs(ex-bx)+abs(ey-by);
73         if((best+t)&1)//首先判断一下,如果最短路径和要走的步数奇偶性不同,就直接输出NO
74         {
75              printf("NO\n");
76              continue;
77         }
78         map[bx][by]='X';
79         DFS(bx,by);//深搜
80         if(flag)
81         printf("YES\n");
82         else
83         printf("NO\n");
84     }
85     return 0;
86 }

下面看下修剪前后的时间差距

 

 
第三个是没剪枝的时候
第二个是没加满足情况就回溯那一句,在上面提到过
第一个是最后修剪成功
 
前两个在杭电都是超时的!
 
不懂得可以在下面提问,一定会尽快回复大家!谢谢
 
 
posted @ 2015-08-09 16:23  Eric_keke  阅读(257)  评论(0编辑  收藏  举报