HDU1010 Temper of the Bone

剛剛上實驗課,榨果汁。。。自覺學不到什麼東西,就來到了機房,看看HDU上的題。一道搜索,其中包含了幾個我從沒想到過的剪枝方法,例如奇偶剪枝、路徑剪枝還有在主函數中的一個剪枝,諸見代碼與註釋,雖然看起來沒什麼用的剪枝沒準會遇到變態的測試數據導致最後的完蛋,所以只要能想到的剪枝就儘量寫上去。
注:這題的代碼來自標程。

/*
    Exe.Time    Exe.Memory  Code Len.   Language    Author
    62MS        1676K       2081 B      C++         int9
*/

// PPT上的標程
#define LOCAL


#include <iostream>
#include <cmath>
#include <fstream>

using namespace std;

// 迷宮地圖
// X:牆壁,小狗不能進入
// S:小狗所處位置
// D:迷宮的門
// .:空格

char map[9][9];
int n, m, t, di, dj;    // (di, dj):門的位置
bool escape;

int dir[4][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};

/*
    1 1 1 1 1 1 1 1 1
    1 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 1
    1 1 1 1 1 1 1 1 1

*/

void dfs(int si, int sj, int cnt) // 表示在si,sj要求在cnt秒達到門的位置
// cnt 是當前的時間而非上述的註釋
{
    int i, temp;
    if (si > n || sj > m || si <= 0 || sj <= 0) return;

    if (si == di && sj == dj && cnt == t) {
        escape = 1;
        return;
    }

    // 此處奇偶剪枝和路徑剪枝
    temp = (t - cnt) - abs(si - di) - abs(sj - dj);
    if (temp < 0 || temp & 1) return;

    for (i = 0; i < 4; i++) {
        if (map[si + dir[i][0]][sj + dir[i][1]] != 'X') {
            map[si + dir[i][0]][sj + dir[i][1]] = 'X';
            dfs(si + dir[i][0], sj + dir[i][1], cnt + 1);
            if (escape) return;
            // backtrack
            map[si + dir[i][0]][sj + dir[i][1]] = '.';
        }
    }
    return;
}

// 到此這個DFS函數已經頗有效率,如果在此main函數中不進行剪枝也是可以的

int main() {
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
#endif

    std::ios::sync_with_stdio(false);

    int i, j, si, sj;
    while (cin >> n >> m >> t && n && m && t) {
        // 此處數據是將要對對某些破爛數據的剪枝,可以刪除掉
        int wall = 0;


        // Input
        for (i = 1; i <= n; i++) {
            for (j = 1; j <= m; j++) {
                cin >> map[i][j];
                if (map[i][j] == 'S') { si = i; sj = j; }
                else if (map[i][j] == 'D') { di = i; dj = j; }
                // 對牆數量的剪枝
                else if (map[i][j] == 'X') wall++;
            }
        }

        if (n * m - wall <= t) {
            cout << "NO" << endl;
            continue;
        }

        escape = 0;


        // 上述剪枝完畢,估計也沒多少數據會用到上面這個剪枝,對效率提升不大

        map[si][sj] = 'X';
        dfs(si, sj, 0);

        if (escape) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
    return 0;

}

同樣是對於矩陣的搜索,這題的矩陣範圍不大,但是測試組數貌似會很多。

發佈了38 篇原創文章 · 獲贊 4 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章