POJ 2488 A Knight's Journey(dfs + 打印路径)

题意:

一个骑士无聊了,于是进行世界旅行,他的世界是一个矩形棋盘,当他移动的时候,先向一个方向走两个,再在垂直的方向上走一格,不能走出棋盘,我们的任务是找到一条路径,骑士走遍所有的格子,每个走一次,如果有那么一条路,把路径输出,横坐标按字母表顺序从小到大,纵坐标按数字顺序从小到大。如果没有输出“impossible”。

思路:

1. dfs + 回溯。深度遍历去寻找一个可行的路径,如果某一条路径行不通,则回溯,把一些标志位去掉。

2. 如果最终走得通,则吧 succ 位设置 true,由于路径是对于字典序排的,所以对于剩下的情况不作处理,直接 return 即可。

3. 对于路径的压栈、出栈操作比较出彩,几个标志位的设置如 PC, succ也很漂亮。

#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN = 50;
const int MAXC = 2 * MAXN * MAXN;

bool vis[MAXN][MAXN], succ;
char path[MAXC];
int P, Q, PC;
int dir[8][2] = {-2, -1, -2, 1, -1, -2, -1, 2, 1, -2, 1, 2, 2, -1, 2, 1};

bool judge(int x, int y) {

    if (x > 0 && x <= Q && y > 0 && y <= P && !vis[x][y]) {
        return true;
    }
    return false;
}

void dfs(int x, int y) {

    if (succ)
        return ;

    vis[x][y] = true;
    path[PC++] = x + 'A' - 1;
    path[PC++] = y + '0'; 

    if (PC == P * Q * 2) {
        succ = true ;
        return ;
    }

    for (int i = 0; i < 8; ++i) {
        int newx = x + dir[i][0];
        int newy = y + dir[i][1];

        if (judge(newx, newy) && !succ) {
            dfs(newx, newy);
            PC -= 2;
            vis[newx][newy] = false;
        }
    }
}

int main()
{
    int cases, cc = 0;
    scanf("%d", &cases);

    while (cases--) {
        scanf("%d%d", &P, &Q);

        memset(vis, false, sizeof(vis));
        memset(path, 0, sizeof(path));
        
        PC = 0, succ = false;
        dfs(1, 1);

        if (succ) {
            printf("Scenario #%d:\n%s\n\n", ++cc, path);
        } else {
            printf("Scenario #%d:\nimpossible\n\n", ++cc);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/kedebug/p/2964002.html