hdu1010 Tempter of the Bone(dfs)

    这一题的dfs算是简单,但是本题难就难在剪枝。不剪枝的dfs也能过但是也稍微做一点优化,才能AC。但是如果使用 奇偶剪枝 的话效果就比优化明显多了
虽然几次优化可以达到405MS(感觉应该是极致了,划线的为奇偶剪枝),但是不如奇偶剪枝一剪就到202MS。
现在我来介绍下奇偶剪枝:
      

首先举个例子,有如下4*4的迷宫,'.'为可走路段,'X'为障碍不可通过

S...
....
....
...D

从S到D的最短距离为两点横坐标差的绝对值+两点纵坐标差的绝对值 = abs(Sx - Dx) + abs(Sy - Dy) = 6,这个应该是显而易见的。

遇到有障碍的时候呢

S.XX
X.XX
...X
...D

你会发现不管你怎么绕路,最后从S到达D的距离都是最短距离+一个偶数,这个是可以证明的

而我们知道:

奇数 + 偶数 = 奇数
偶数 + 偶数 = 偶数

因此不管有多少障碍,不管绕多少路,只要能到达目的地,走过的距离必然是跟最短距离的奇偶性是一致的。

所以,这样对于一部分不可行的方案几乎就是瞬间搞定

下面直接上代码了:

#include <iostream>
#include <stdlib.h>
#include <cstring>
using namespace std;
char maze[10][10];
bool dfs(int x, int y, int T){
    // 剩一步时即可判断是否为出口,找到返回true
    if (T == 1){
        if (maze[x-1][y] == 'D') return true;
        if (maze[x+1][y] == 'D') return true;
        if (maze[x][y-1] == 'D') return true;
        if (maze[x][y+1] == 'D') return true;
        return false;
    }
    else{
        // 标记走过
        maze[x][y] = 'X';
        // 深度优先搜索
        if (maze[x-1][y] == '.' && dfs(x-1, y, T-1)) return true;
        if (maze[x+1][y] == '.' && dfs(x+1, y, T-1)) return true;
        if (maze[x][y-1] == '.' && dfs(x, y-1, T-1)) return true;
        if (maze[x][y+1] == '.' && dfs(x, y+1, T-1)) return true;
        // 还原走过
        maze[x][y] = '.';
        return false;
    }
}
int main(){
    int sx,sy,gx,gy;
    int N,M,T;
    while(cin>>N>>M>>T,T){
        memset(maze,'X',sizeof(maze));
        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++){
                cin>>maze[i][j];
                if(maze[i][j]=='S')
                    sx=i,sy=j;
                else if(maze[i][j]=='D')
                    gx=i,gy=j;
            }
        }
        if( ( abs(sx-gx)+abs(sy-gy) - T ) & 1 )
        //奇偶剪枝
            cout<<"NO"<<endl;
        else{
            if(dfs(sx,sy,T))
                cout<<"YES"<<endl;
            else
                cout<<"NO"<<endl;
        }
    }
    return 0;
}


 

你可能感兴趣的:(hdu1010 Tempter of the Bone(dfs))