• HDU 1010 Tempter of the Bone (DFS + 奇偶剪枝)



    **链接 : ** Here!

    思路 : 如果直接爆搜的话, 会搜到天荒地老.... QAQ ...., 所以就得利用一些技巧, 因为题目说的是小狗能否在 $T (s)$ 能够恰好到达 $Door$ , 所以可以利用 奇偶剪枝剪掉多余搜索

    奇偶剪枝 : 假设只能上下左右移动, 现在起点为 $(sx, sy)​$ , 终点为 $(ex, ey)​$ , 要求恰好 $T​$ 步从 $(sx, sy)​$ 到达 $(ex, ey)​$, 因此可以得到一个结论, 若 $T - [abs(sx - ex) + abs(sy - ey)] 为奇数, 则无法在T步恰好到达, 反之则可以​$, 再补充一点 $ [abs(sx - ex) + abs(sy - ey)] ​$ 称为曼哈顿路径


    /*************************************************************************
    	> File Name: E.cpp
    	> Author: 
    	> Mail: 
    	> Created Time: 2017年11月26日 星期日 10时51分05秒
     ************************************************************************/
    
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    #define MAX_N 10
    int N, M, T;
    int vis[MAX_N][MAX_N];
    char G[MAX_N][MAX_N];
    int dx[4] = {0, 0, -1, 1};
    int dy[4] = {1, -1, 0, 0};
    bool flag = 0;
    
    struct Point {
        Point() : x(0), y(0){}
        Point(int x, int y) : x(x), y(y){}
        int x, y;
    };
    Point st, ed;
    
    int manhattan_dist(Point sre, Point des) {
        return fabs(sre.x - des.x) + fabs(sre.y - des.y);
    }
    int check(Point pt) {
        if (pt.x < 0 || pt.x >= N || pt.y < 0 || pt.y >= M) return 0;
        if (vis[pt.x][pt.y]) return 0;
        if (G[pt.x][pt.y] == 'X') return 0;
        return 1;
    }
    // 直接曼哈顿路径 + 奇偶剪枝
    void DFS(Point pt, int now_time) {
        if (pt.x == ed.x && pt.y == ed.y && now_time == T) { flag = 1; return; }
        if (flag) return;
    
        // 曼哈顿路径 + 奇偶剪枝
        int tstep = T - now_time - manhattan_dist(pt, ed);
        if (tstep < 0 || (tstep & 1)) return;
    
        vis[pt.x][pt.y] = 1;
        for (int i = 0 ; i < 4 ; ++i) {
            Point temp(pt.x + dx[i], pt.y + dy[i]);
            if (!check(temp)) continue;
            vis[temp.x][temp.y] = 1;
            DFS(temp, now_time + 1);
            vis[temp.x][temp.y] = 0;
        }
    }
    
    void solve() {
        memset(vis, 0, sizeof(vis));
        for (int i = 0 ; i < N ; ++i) {
            for (int j = 0 ; j < M ; ++j) {
                if (G[i][j] == 'S') 
                    st.x = i, st.y = j;
                if (G[i][j] == 'D') 
                    ed.x = i, ed.y = j;
            }
        }
        vis[st.x][st.y] = 1;
        DFS(st, 0);
        if (flag) {
            printf("YES
    ");
        } else {
            printf("NO
    ");
        }
    }
    
    int main() {
        // freopen("./in.in", "r", stdin);
        while (scanf("%d%d%d", &N, &M, &T) != EOF) {
    		flag = 0;
            if (N == 0 && M == 0 && T == 0) break;
            memset(G, 0, sizeof(G));
            for (int i = 0 ; i < N ; ++i) {
                getchar();
                scanf("%s", G[i]);
            }
            solve();
        }
        return 0;
    }
    
    
  • 相关阅读:
    CentOs图形界面的开启与关闭
    在CentOS上安装ZooKeeper集群
    CentOs中mysql的安装与配置
    CentOS 6.5 下安装 Redis 2.8.7
    apt-get 与 yum的区别 (转)
    centos 命令大全
    ctrl+c,ctrl+d,ctrl+z在linux中意义
    Jedis 例子(demo)大全
    gradle init.gradle的文件配置 使用
    Java使用Jetty实现嵌入式Web服务器及Servlet容器
  • 原文地址:https://www.cnblogs.com/WArobot/p/7903303.html
Copyright © 2020-2023  润新知