【题解】Tempter of the Bone HDU - 1010 ⭐⭐【经典问题 奇偶性剪枝】

暑假的时候,小明和朋友去迷宫中寻宝。然而,当他拿到宝贝时,迷宫开始剧烈震动,他感到地面正在下沉,他们意识到这是一个陷阱!他们想尽一切办法逃出去。
迷宫是一个大小为 N*M 的长方形,迷宫中有一扇门。一开始,门是关着的,他会在第 t 秒的时间打开。因为,小明和朋友必须在第 t 秒到大门口。每一秒,他都可以向上下左右四个方向移动一个点。一旦他移动了,他刚才所在的点就消失,(这意味着他不能回到他已经走过的点)。他不能在一个点上停留超过一秒,并且不能走障碍点。小明和朋友能安全的逃出吗?

Input

输入由多个测试用例组成。每个测试用例的第一行包含三个整数 N、M 和 T ( 1 < N , M < 7 ; 0 < T < 50 ),分别表示迷宫的大小和门打开的时间。接下来的N行给出迷宫布局,每一行包含M个字符。下列字母分别表示:

“X”: 一堵墙,小明和朋友不能在上面停留
“S”: 起点
“D”: 门
“.”: 可以走的点

输入以 3 个 0 时结束。这个测试用例不需要处理。

Output

对于每组样例输出一行。
如果小明能够安全逃出,输出 “YES” ,否则输出 “NO”。

Examples

Sample Input
4 4 5
S.X.
…X.
…XD

3 4 5
S.X.
…X.
…D
0 0 0
Sample Output
NO
YES

Hint




题意:

题解:

首先就是最经典的奇偶性剪枝, 观察样例我们可以发现, 对于两点之间曼哈顿距离为奇数的, 则只能在奇数时间内到达. 为偶数的, 之内在偶数时间内到达. 这样的话我们判断到不匹配的直接就剪掉了.
还有一个小剪枝, 就是如果我们发现可走的格子数量比时间还要多, 自然也要剪掉了.
剩下的就是直接搜了, 注意要求恰好 t==T

经验小结:


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const int inf = 1<<30;
const int maxn = 10;

int N, M, T;
int sx, sy, ex, ey;
bool mp[maxn][maxn], vis[maxn][maxn];
int act[4][2] = {{0,1},{1,0},{-1,0},{0,-1}};
bool Dfs(int x, int y, int t){
    if(t > T) return false;         //剪枝
    if(x==ex && y==ey && t==T) return true; //终点
    int cx, cy;
    for(int i = 0; i < 4; i++){
        cx = x+act[i][0], cy = y+act[i][1];
        if(cx>0&&cx<=N&&cy>0&&cy<=M && !mp[cx][cy] && !vis[cx][cy]){
            vis[cx][cy] = true;
            if(Dfs(cx, cy, t+1)) return true;
            vis[cx][cy] = false;
        }
    }
    return false;
}
int main()
{
    char c;
    while(cin>>N>>M>>T, N||M||T){
        ms(mp, 0);  ms(vis, 0);
        int block = 0;
        for(int i = 1; i <= N; i++)
            for(int j = 1; j <= M; j++){
                cin >> c;
                if(c=='S') sx = i, sy = j;
                else if(c=='D') ex = i, ey = j;
                else if(c=='X') mp[i][j] = 1, ++block;
            }
    //
        if(T>(N*M-block) || (abs(sx-ex)+abs(sy-ey))%2!=T%2){ //剪枝
            cout << "NO" << endl;
            continue;
        }
        vis[sx][sy] = true;
        if(Dfs(sx, sy, 0)) cout << "YES" << endl;
        else cout << "NO" << endl;
    }

	return 0;
}

你可能感兴趣的:(搜索)