zoukankan      html  css  js  c++  java
  • HDU 1010 Tempter of the Bone --- DFS

      HDU 1010

      题目大意:给定你起点S,和终点D,X为墙不可走,问你是否能在 T 时刻恰好到达终点D。

      参考: 奇偶剪枝

      奇偶剪枝简单解释:

        在一个只能往X、Y方向走的方格上,从起点到终点的最短步数为T1,并记其他任意走法所需步数为T2,则T2-T1一定为偶数。

        即若某一点到终点的最短步数为T1,且T3-T1为奇数,则一定无法话费T3步恰好到达终点。

    /*HDU 1010 ------ Tempter of the Bone DFS*/
    #include <cstdio>
    #include <cstring>
    
    int m, n, t, startx, starty, endx, endy;
    char mapp[10][10];
    bool visit[10][10], ans, flag;
    
    /*求a-b的绝对值*/
    int abs(int a, int b){
        if (a < b)
            return b - a;
        else
            return a - b;
    }
    
    /*搜索从i,j处走走到出口的结果 i j为横纵坐标 c为当前已走步数*/
    void DFS(int i, int j, int c){
        if (flag || c > t || i <= 0 || i > n || j <= 0 || j > m)
            return;
        if (mapp[i][j] == 'D' && c == t){
            ans = flag = 1;
            return;
        }
        int tmp = abs(i, endx) + abs(j, endy); //最短可到距离
        tmp = t - c - tmp; //t-c为剩余可走步数 减去最短距离为 剪纸
        if (tmp & 1) //若剪枝后tmp为奇数 一定不可到达
            return;
    
        //左边的点可以访问
        if (!visit[i - 1][j] && mapp[i - 1][j] != 'X'){
            visit[i - 1][j] = true;
            DFS(i - 1, j, c + 1);
            visit[i - 1][j] = false;
        }
        //右边的点可以访问
        if (!visit[i + 1][j] && mapp[i + 1][j] != 'X'){
            visit[i + 1][j] = true;
            DFS(i + 1, j, c + 1);
            visit[i + 1][j] = false;
        }
        //上边的点可以访问
        if (!visit[i][j - 1] && mapp[i][j - 1] != 'X'){
            visit[i][j - 1] = true;
            DFS(i, j - 1, c + 1);
            visit[i][j - 1] = false;
        }
        //下边的点可以访问
        if (!visit[i][j + 1] && mapp[i][j + 1] != 'X'){
            visit[i][j + 1] = true;
            DFS(i, j + 1, c + 1);
            visit[i][j + 1] = false;
        }
    }
    
    int main()
    {
        //n行m列t步
        while (scanf("%d%d%d", &n, &m, &t) == 3 && (m + n + t)){
            int k = 0;
            memset(visit, 0, sizeof visit);
            //i,j取1是为了判别时数组不越界
            for (int i = 1; i <= n; ++i){
                scanf("%s", mapp[i]+1);
                for (int j = 1; j <= m; ++j){
                    if (mapp[i][j] == 'X'){
                        ++k; //记录墙的数量
                    }
                    else if (mapp[i][j] == 'S'){
                        startx = i;  //记录起始点
                        starty = j;
                        visit[i][j] = true;
                    }
                    else if (mapp[i][j] == 'D'){
                        endx = i; //记录终点
                        endy = j;
                    }
                }//for(j)
            }//for(i)
    
            ans = flag = 0;
            if (n*m - k - 1 >= t) //总数-墙-起点 需大于等于 步数
                DFS(startx, starty, 0);
            if (ans)
                printf("YES
    ");
            else
                printf("NO
    ");
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    借鉴文章记录
    三方框架
    常用第三方库记录
    ios block 类型
    ios runtime部分事例方法说明
    ios url网址相关问题解说
    mysql迁移数据库函数中的坑
    mysql的事务隔离级别
    MySQL数据库的默认隔离级别为什么是可重复读
    实时查看mysql连接数
  • 原文地址:https://www.cnblogs.com/tommychok/p/5020588.html
Copyright © 2011-2022 走看看