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
原文地址:https://www.cnblogs.com/tommychok/p/5020588.html