POJ 2488 A Knight's Journey

本文介绍了一道经典的骑士游历问题,并提供了一个求解方法。通过特定的深度优先搜索策略,确保按照字典序输出最小的行走路线。代码中详细展示了如何实现这一策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:

给定一个p*q的棋盘(p行q列或者q行p列都行,我是理解为q行p列),一个Knight在该棋盘上行走(走日字),可以从棋盘的任意方格出发,要求不重复的走完所有的方格,输出字典序最小的行走路线。q行:A、B、C...,p列:1、2、3...p;题目连接:http://poj.org/problem?id=2488

解题思路:

一道经典的“骑士游历问题”,网上说是DFS水题,可我觉得还是有些难度。毕竟DFS学的不好。

由于题目要求是按照字典序输出行走路线,那么在深搜的时候对扩展节点的搜索顺序是有要求的,搜索顺序如下所示:



代码:

#include<iostream>
#include<fstream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<sstream>
#include<cassert>
using namespace std;
#define LL __int64
int p,q;
int vis[30][30];
int dx[]={-2,-2,-1,-1,1,1,2,2};  //搜索顺序有特殊要求
int dy[]={-1,1,-2,2,-2,2,-1,1};
int th=0;
int step[30][2];   //记录行走的路线
bool dfs(int x,int y,int num){
    if(num==p*q){           //走完所有的方格
        step[th][0]=x;
        step[th++][1]=y+1;
        return true;
    }
    vis[x][y]=1;
    for(int i=0;i<8;i++){
        int tmpx,tmpy;
        tmpx=x+dx[i];
        tmpy=y+dy[i];
        if(tmpx>=0 && tmpx<q && tmpy>=0 && tmpy<p && !vis[tmpx][tmpy]){
            if(dfs(tmpx,tmpy,num+1)){
               step[th][0]=x;step[th++][1]=y+1;
                return true;
            }
        }

    }
    vis[x][y]=0;
    return false;
}
int main(){
    int n;
    scanf("%d",&n);
    for(int k=1;k<=n;k++){
        scanf("%d%d",&p,&q);
        memset(vis,0,sizeof(vis));
        int flag=0;
        for(int i=0;i<q;i++){
            for(int j=0;j<p;j++){
                th=0;
                if(dfs(i,j,1)){
                    flag=1;
                    break;
                }
            }
            if(flag)
                break;
        }
        printf("Scenario #%d:\n",k);
        if(!flag){
            printf("impossible\n");
        }
        else{
            for(int i=th-1;i>=0;i--){
                printf("%c%d",step[i][0]+'A',step[i][1]);
            }
            printf("\n");
        }
        if(k<n)
            printf("\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值