HDOJ1010.Tempter of the Bone

試題請參見: http://acm.hdu.edu.cn/showproblem.php?pid=1010

題目概述

The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.

The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.

解題思路

迷宮問題, 深度優先搜索(回溯).
不過需要奇偶剪枝.

遇到的問題

一開始陷入了TLE, 之後又陷入了WA.

  1. 需要引入奇偶剪枝, 也就是說, 當剩餘步數( = 總步數 - 當前步數)爲奇數時, 一定無法到達;
  2. 一開始是純暴力搜索, 並沒有回溯. 引入了isVisited數組之後成功解決;
  3. 一開始的思路是, 使用DFS計算出最小的步數, 然後再用奇偶剪枝, 但是事實證明, 這方法不可行(測試數據見下一節).

參考的測試數據

其中第2個數據就是爲什麼計算最小步數是不可行的原因.

源代碼

#include <iostream>
#include <cmath>

const int MAX_SIZE = 10;
bool isAccessible[MAX_SIZE][MAX_SIZE];
bool isVisited[MAX_SIZE][MAX_SIZE];
bool isExitReached = false;

void traverseMap(int currentX, int currentY, int exitX, int exitY, int currentSteps, int n, int m, int t) {
    if ( currentX < 0 || currentY < 0 || currentX >= n || currentY >= m ) {
        return;
    }
    if ( isExitReached ) {
        return;
    }

    if ( currentSteps == t && currentX == exitX && currentY == exitY ) {
        isExitReached = true;
        return;
    }
    // Branch Cutting
    int restSteps = t - currentSteps - std::abs(currentX - exitX) - std::abs(currentY - exitY);
    if ( restSteps < 0 || restSteps % 2 != 0 ) {
        isExitReached = false;
        return;
    }

    isVisited[currentX][currentY] = true;
    if ( !isVisited[currentX][currentY - 1] && isAccessible[currentX][currentY - 1] ) {
        traverseMap(currentX, currentY - 1, exitX, exitY, currentSteps + 1, n, m, t);
    }
    if ( !isVisited[currentX][currentY + 1] && isAccessible[currentX][currentY + 1] ) {
        traverseMap(currentX, currentY + 1, exitX, exitY, currentSteps + 1, n, m, t);
    }
    if ( !isVisited[currentX - 1][currentY] && isAccessible[currentX - 1][currentY] ) {
        traverseMap(currentX - 1, currentY, exitX, exitY, currentSteps + 1, n, m, t);
    }
    if ( !isVisited[currentX + 1][currentY] && isAccessible[currentX + 1][currentY] ) {
        traverseMap(currentX + 1, currentY, exitX, exitY, currentSteps + 1, n, m, t);
    }
    isVisited[currentX][currentY] = false;
}

int main() {
    int n = 0, m = 0, t = 0;
    while ( std::cin >> n >> m >> t ) {
        if ( n == 0 && m == 0 && t == 0 ) {
            break;
        }

        isExitReached = false;
        int startX = 0, startY = 0;
        int exitX = 0, exitY = 0;
        char mapPoint;
        for ( int i = 0; i < n; ++ i ) {
            for ( int j = 0; j < m; ++ j ) {
                std::cin >> mapPoint;

                if ( mapPoint == 'S' ) {
                    isAccessible[i][j] = true;
                    startX = i;
                    startY = j;
                } else if ( mapPoint == 'D' ) {
                    isAccessible[i][j] = true;
                    exitX = i;
                    exitY = j;
                } else if ( mapPoint == 'X' ) {
                    isAccessible[i][j] = false;
                } else if ( mapPoint == '.' ) {
                    isAccessible[i][j] = true;
                }
            }
        }

        traverseMap(startX, startY, exitX, exitY, 0, n, m, t);
        if ( isExitReached ) {
            std::cout << "YES" << std::endl;
        } else {
            std::cout << "NO" << std::endl;
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章