POJ2488のバックトラック深さ優先探索+

POJ2488

タイトル

  ナイトボードはパトロール一度散歩、各グリッドをパトロールする図に示されており、全ての格子をパトロールしなければなりません。そのようなパスは、出力が不可能な、存在する場合は、ナイト・ツアーパスを出力し、ボードの行数と列pをqの数を考えます。


移動の8種類の騎士

移動の8種類の1ナイト

  ナイト・ツアー問題のバージョンを簡略化し、ハミルトン経路は特別な問題であるが、それは線形時間で解決することができる (\ ^ {[1]})\

サンプル入力

3
1 1
2 3
4 3

サンプル出力

Scenario #1:
A1

Scenario #2:
impossible

Scenario #3:
A1B3C1A2B4C2A3B1C3A4B2C4

アルゴリズムの考え方

  深さ優先探索(深さ優先探索、DFS)アルゴリズムは、以下の擬似コード\(^ {[2]} \)


DFSアルゴリズムの擬似コード

図2 DFS擬似コード

  DFSトラバーサルアルゴリズム図に示されているが、図3の深さ優先探索ツリーを作成しますが、探索木から見ることができ、オリジナルのDFSアルゴリズムは、我々が望むものではありません、私たちが望むことだけDFSアルゴリズムたら、各グリッドをパトロールすることです、を意味している我々は(ツリーを分岐していない)探索木の市松模様の深さの番号が必要です。それはどのように改善するのか?我々はuのノードにアクセスする場合、DFSはこの時点で進行することができない木の深さを示すために使用されるカウンタcntを設定し、我々は、我々は、パスがない場合は見つけるためにしようと等しい場合深さは、チェッカーボードグリッドの数に等しいかどうかを確認します我々はノードに現在のノードをリセットする必要があり、その後、このパスが間違っている見つけることを、等しいが検索され、その後、前のノードに戻り、前のノード(すなわち、来年5月の次の子ノードされていませんパトロールグリッド)DFSを行いました。コード内のコメントを参照することができます理解されるであろう。

深さ優先探索木

3深さ優先探索木

  1つのWAポイント:複数のパスは、パトロール、要求優先順位辞書出力経路の被写体が存在する場合辞書最初のパスをフロントB C.のですなわち、A1B1C1場合、であり、そしてA1C1B1パス許可され、A1B1C1を選択します 実際には、これは単なる辞書式の優先順位を確保するために、左から右の「列」にスキャンし、達成することは非常に良いです。

コード

結果:372KB、0msとします。

#include <stdio.h>
#include <string.h>
#include <vector>

int n, p, q;
int delta_row[8] = { -1, 1, -2, 2, -2, 2, -1, 1 };//DFS的搜索顺序,按照列从左往右的顺序进行搜索。
int delta_col[8] = { -2, -2, -1, -1, 1, 1, 2, 2 };//即搜索的优先级(-1, -2)=(1, -2)>(-2, -1)=(2, -1)>(-2, 1)=(2, 1)>(-1, 2)=(1, 2),等于的意思是先搜索哪一个不影响字典序
int explored[30][30];//标记是否为已搜索过的节点
int cnt;
struct Node {
    int row, col;
} path[30];//记录下路径

void Init() {
    memset(explored, 0, sizeof(explored));
    cnt = 0;
}

bool Dfs(int row, int col) {
    explored[row][col] = 1;//标记为已搜索的节点
    cnt++;//深度加1
    path[cnt].row = row;
    path[cnt].col = col;
    for (int i = 0; i < 8; i++) {//按照列从左往右的顺序进行搜索
        int row_new = row + delta_row[i], col_new = col + delta_col[i];
        if (row_new >= 1 && row_new <= p && col_new >= 1 && col_new <= q && !explored[row_new][col_new]) {//骑士要去巡逻的新节点(row_new, col_new)在棋盘范围内且未搜索过
            if (Dfs(row_new, col_new))//若找到路径,直接break,一层层跳出递归,若没找到,对下一个优先级的要去巡逻的新节点进行搜索
                break;
        }
    }
    if (cnt == p * q)//若深度为p*q,说明我们找到了路径
        return true;
    else {//若没找到,回溯到前一节点,当前节点置为未搜索的节点,树的深度减1
        explored[row][col] = 0;
        cnt--;
        return false;
    }
}

int main() {
    scanf("%d", &n);
    for (int t = 1; t <= n; t++) {
        scanf("%d %d", &p, &q);
        printf("Scenario #%d:\n", t);
        Init();
        if (Dfs(1, 1)) {
            for (int i = 1; i <= p * q; i++)
                printf("%c%c", 'A' + path[i].col - 1, '1' + path[i].row - 1);
            printf("\n");
        }
        else
            printf("impossible\n");
        if (t != n)
            printf("\n");
    }
    return 0;
}

参考:

[1] ナイトAPOS・ツアー
[2] アルゴリズムの設計

おすすめ

転載: www.cnblogs.com/wtyuan/p/12106652.html