poj2488 A Knight's Journey

Background 
The knight is getting bored of seeing the same black and white squares again and again and has decided to make a journey 
around the world. Whenever a knight moves, it is two squares in one direction and one square perpendicular to this. The world of a knight is the chessboard he is living on. Our knight lives on a chessboard that has a smaller area than a regular 8 * 8 board, but it is still rectangular. Can you help this adventurous knight to make travel plans? 

Problem 
Find a path such that the knight visits every square once. The knight can start and end on any square of the board.

Input

The input begins with a positive integer n in the first line. The following lines contain n test cases. Each test case consists of a single line with two positive integers p and q, such that 1 <= p * q <= 26. This represents a p * q chessboard, where p describes how many different square numbers 1, . . . , p exist, q describes how many different square letters exist. These are the first q letters of the Latin alphabet: A, . . .

Output

The output for every scenario begins with a line containing "Scenario #i:", where i is the number of the scenario starting at 1. Then print a single line containing the lexicographically first path that visits all squares of the chessboard with knight moves followed by an empty line. The path should be given on a single line by concatenating the names of the visited squares. Each square name consists of a capital letter followed by a number. 
If no such path exist, you should output impossible on a single line.

Sample Input

3
1 1
2 3
4 3

Sample Output

Scenario #1:
A1

Scenario #2:
impossible

Scenario #3:
A1B3C1A2B4C2A3B1C3A4B2C4


题意: 
给出一个p行q列的国际棋盘,马可以从任意一个格子开始走,问马能否不重复的走完所有的棋盘。如果可以,输出按字典序排列最小的路径。打印路径时,列用大写字母表示(A表示第一列),行用阿拉伯数字表示(从1开始),先输出列,再输出行。

题解: 
基础dfs进行暴力,开一个数组沿途记录路径,注意因为要求字典序最小,所以每次都从 A1 这个位置开始搜,且调整好每次搜索的方向以保证其字典序最小,注意输出格式。

#include<iostream>

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

using namespace std;

int m,n;
bool vis[500][500];
int dx[]={-1, 1, -2, 2,-2, 2,-1, 1};
int dy[]={-2,-2, -1,-1, 1, 1, 2, 2};//严格按照这个顺序输出的才是字典序
bool ok;
struct node{
 int row;
 int col;
}path[500];

void dfs(int i,int j,int cnt){
    path[cnt].col=j;
    path[cnt].row=i;//记录路径
    if(cnt==m*n) {ok=true;return;}
    int a,b;
    for(int k=0;k<8;k++){
        a=i+dx[k];
        b=j+dy[k];
        if(a<=m&&a>=1&&b<=n&&b>=1&&!vis[a][b]){
            vis[a][b]=true;
            dfs(a,b,cnt+1);//深度优先搜索
            if(ok==true) return;//只有访问到最后一个点的情况下ok才会为true
            vis[a][b]=false;//能到这一步说明八步都不和要求,擦除这个点的访问记录
            }
    }
    return;
}
int main(){
    int T;

    int c=1;
    cin>>T;
    while(T--){
        cin>>m>>n;
        if(m==1&&n==1){
            cout<<"Scenario #"<<c<<":"<<endl;
            cout<<"A1"<<endl<<endl;
            continue;
        }else{
            ok=false;//一定要访问到最后一个点才能更改ok的值
            memset(vis,false,sizeof(vis));
            vis[1][1]=true;
            dfs(1,1,1);
            if(!ok){
                cout<<"Scenario #"<<++c<<":"<<endl;
                cout<<"impossible"<<endl<<endl;//说明深搜完还是没能访问到最后一个点,则搜索失败
            }else{
                cout<<"Scenario #"<<++c<<":"<<endl;
                for(int i=1;i<=m*n;i++){
                    printf("%c%d",path[i].col+'A'-1,path[i].row);

                    }
                    printf("

");

                    //cout<<path[i].row+'A'-1<<path[i].col<<endl<<endl;
            }
        }


    }
return 0;
}
原文地址:https://www.cnblogs.com/jokerspace/p/6752891.html