hdu1010(DFS + 奇偶剪枝)

来源:互联网 发布:苹果手机 截图软件 编辑:程序博客网 时间:2024/05/16 17:39

Tempter of the Bone

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

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

Source
ZJCPC2004

转载自:http://blog.csdn.net/ld_1090815922/article/details/70665872
解题思路:一看题意就知道是一道搜索得题,果断用深搜
剪枝方法1:如果可以走的地板数目小于给定的时间,那么绝对不可能得逃出。
剪枝方法2:还有就是狗走到门的时间必须和题目给定的时间是同奇同偶的,否则也不能在指定的那秒到达门,也不可能得逃出。
剪掉这两种情况后,就用深度搜索来做。从起点出发,深搜周围的路,走过的路就更新为墙,一直搜索下去,如果是一条“死路“”就回溯,把可能的路都搜索一遍过去,看看是否有“活路”。
这最用到最主要的剪枝方法就是奇偶剪枝,也简单介绍下:
可以把地图看成这样:
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 走到任意 0 或从任意1到任意1始终是偶数步;
结论(对于此题):
所以当遇到从 0 走向 0 但是要求时间是奇数的,或者,
从 1 走向 0 但是要求时间是偶数的 都可以直接判断不可能到达。

解析的很清楚,感觉有了解法代码就好写了,但死就死在细节上,进dfs之前我visit数组没有更新起始点的值,以至于遍历可以走起始点使得秒数到达t,加了一个visit[sx][sy] = 1;

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int N = 10;char mp[N][N];int visit[N][N];//位移向量const int nx[4] = {0,1,0,-1};const int ny[4] = {1,0,-1,0};int n,m,t;int finx,finy;int first;void dfs(int x,int y,int path){    if(first == 1) return;//已经找到目标了    /*if(abs((x%2+y%2)%2 - (finx%2+finy%2)%2) == 0){        if(t % 2 != 0)            return ;    }    else{        if(t % 2 == 0){            return ;        }    }*/    if(path > t) return;    if((t - path - abs(finx - x) - abs(finy - y)) % 2 == 1)        return ;    if(mp[x][y] == 'D')    {        if(path == t){            first = 1;        }        return ;    }    for(int i = 0;i < 4; ++i)    {        int next_x = x + nx[i];        int next_y = y + ny[i];        if(next_x >= 0 && next_y >= 0 && next_x < n && next_y < m)        {            if(mp[next_x][next_y] != 'X' && visit[next_x][next_y] == 0){                visit[next_x][next_y] = 1;                dfs(next_x,next_y,path + 1);                visit[next_x][next_y] = 0;            }        }    }}int main(){    while(~scanf("%d %d %d",&n,&m,&t))    {        if(!n && !m && !t){            break;        }        for(int i = 0;i < n;++i)        {            scanf("%s",mp[i]);        }        /*for(int i = 0;i < n;++i)        {            for(int j = 0;j < m;++j)            {                printf("%c",mp[i][j]);            }            cout << endl;        }*/        int p,q;        int w = 0;        for(int i = 0;i < n;++i)        {            for(int j = 0;j < n;++j)            {                if(mp[i][j] == 'S'){                    p = i;q = j;                }                if(mp[i][j] == 'D'){                    finx = i;                    finy = j;                }                if(mp[i][j] == 'X'){                    w++;                }            }        }        if(n * m > t){            printf("NO\n");            continue;         }        int path = 0;        first = 0;        memset(visit,0,sizeof(visit));        visit[p][q] = 1;        dfs(p,q,path);        if(first == 1){            printf("YES\n");        }        else{            printf("NO\n");        }    }    return 0;}