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): 78529    Accepted...

Tempter of the Bone

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


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
 

Recommend
JGShining   |   We have carefully selected several similar problems for you:   1016  1241  1072  1312  1026 
 


这道题啊,折磨了我好久,开始觉得,哦,BFS做就好了,但是范例能过,而实际上却不是合适办法,所以如果对于这道题还是有疑问的同学,只要看看这样一副图就好了。

2 4 7
S..D
....
所以最后参考大神们的代码,解决了本题中的关键问题。
这幅图的答案应该是yes,但是BFS的特点,就是只会保持同一层的而不能像DFS一样将整条路都递归出来,这样的好处是因为本题不能回头,所以每一条路的寻找都不能影响到其他的路径的寻找,每一次标记然后递归后要把标记去掉,所以这道题用回溯法。而且还有奇偶剪枝。

对于奇偶剪枝因为如果对于任何一个位置所在,还需要走的距离是奇数而剩下的时间是偶数,那么可以直接不考虑这条路了,主人公活不了的。直接return掉好了。

所以需要这样来避免时间上被卡住。

代码君

#include<cstdio>
#include<cmath>
#include<cstring>

using namespace std;
int   vid[9][9];
char  way[9][9];
int m,n,t;
bool flag = false;
struct Steps{
    int x,y;
};
Steps   walk,en;
const int mov[4][2] = {0,1,0,-1,1,0,-1,0};
void backtrack(int bx,int by,int ust){
    int need;
    if(flag)
        return;
    if(ust == t){
        if(bx == en.x && by == en.y){
            flag = true;
            return;
        }
    }
    need = fabs(bx - en.x)+fabs(by - en.y);
    int temp = t - ust - need;
    if(temp < 0||temp&1){
        return;
    }
    for(int i = 0;i < 4;i++){
        int tx,ty;
        tx = bx + mov[i][0];
        ty = by + mov[i][1];
        if(tx >= 0 && ty >= 0 && tx < n && ty < m && (way[ty][tx] == '.' || way[ty][tx] == 'D') && !vid[ty][tx]){
            vid[ty][tx] = 1;
            backtrack(tx,ty,ust+1);
            vid[ty][tx] = 0;
        }
    }
}
int main(){
    while(~scanf("%d %d %d",&m,&n,&t) && m){
        memset(way,'X',sizeof(way));
        flag = false;
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                scanf(" %c",&way[i][j]);
                if(way[i][j] == 'S'){
                    walk.x = j;
                    walk.y = i;
                }
                if(way[i][j] == 'D'){
                    en.x = j;
                    en.y = i;
                }
            }
        }
        memset(vid,0,sizeof(vid));
        vid[walk.y][walk.x] = 1;
        backtrack(walk.x,walk.y,0);
        if(flag)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return  0;
}


相关文章
|
9月前
|
算法
class065 A星、Floyd、Bellman-Ford与SPFA【算法】
class065 A星、Floyd、Bellman-Ford与SPFA【算法】
63 0
|
8月前
【洛谷 P1219】[USACO1.5]八皇后 Checker Challenge 题解(深度优先搜索+回溯法)
**USACO1.5八皇后挑战**是关于在$n\times n$棋盘上放置棋子的,确保每行、每列及两条主对角线上各有一个且仅有一个棋子。给定$6$作为输入,输出前$3$个解及解的总数。例如,对于$6\times6$棋盘,正确输出应包括解的序列和总数。代码使用DFS解决,通过跟踪对角线占用状态避免冲突。当找到所有解时,显示前三个并计数。样例输入$6$产生输出为解的前三个排列和总数$4$。
53 0
|
9月前
Poj 3255(dijkstra求次短路)
Poj 3255(dijkstra求次短路)
50 0
UVa11710 - Expensive subway(最小生成树)
UVa11710 - Expensive subway(最小生成树)
52 0
UVa11420 - Chest of Drawers(动态规划)
UVa11420 - Chest of Drawers(动态规划)
51 0
HDU7018.Banzhuan(计算几何+贪心)
HDU7018.Banzhuan(计算几何+贪心)
112 0
HDU7018.Banzhuan(计算几何+贪心)
|
机器学习/深度学习 算法 程序员
【算法合集】深搜广搜Prim与Kruskal
广度优先搜索(BFS)又叫广搜,它像一个有远见的人,它是一层一层来实现搜索的,也挺像下楼梯的。 思路: 1.先初始化队列 q; 2.从起点开始访问,并且改变他的状态为已经访问; 3.如果他的队列非空,取出首个元素,将它弹出! 4.如果u == 目标状态,然后对所以与 u 邻近的点进入队列; 5.标记它已经被访问!...............
192 1
LeetCode 70. 爬楼梯 Climbing Stairs
LeetCode 70. 爬楼梯 Climbing Stairs
2021杭电多校第三场-Road Discount-wqs二分+最小生成树
get函数是求出将黑色的边权加上一个值x之后的一个花费,我们会这个函数处理出x=-1000->1000的所有情况,然后将信息储存在save中,然后在询问的时候,直接遍历save集合,遇见满足情况的便直接输出,否则输出-1,虽然没有-1的情况/doge
143 0
2021杭电多校第三场-Road Discount-wqs二分+最小生成树