POJ2488DFS

A Knight's Journey
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 45494 Accepted: 15471

Description

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

Source

TUD Programming Contest 2005, Darmstadt, Germany

    题意:给出制定规格的网格,问马能不能不重复的全部走完,并按字典序输出路径。

    解题思路:这题显然用DFS会简单一些。开始的时候,我想的是:既然是要把所有的格子遍历一遍,而且输出的结果要以字典序的顺序输出,所以只需要调好搜索的顺序,并用数组存下路径即可。然后,经过我的多次调试,终于过了样例,以下是我的最初代码

#include <stdio.h>
#include <memory.h>
#include <string.h>
#define maxn 30

typedef struct road
{
    char p;
    char q;
} T;
T arr[700];
int flag[maxn][maxn],m,n,a=0;
void dfs(int r,int s)
{
    if(r<0||r>=m||s<0||s>=n) return;
    if(flag[r][s]!=0) return;
    flag[r][s]=1;
    arr[a].p=s+'A';
    arr[a].q=r+'1';
    a++;
    dfs(r+2,s+1);
    dfs(r+2,s-1);
    dfs(r-2,s-1);
    dfs(r-2,s+1);
    dfs(r+1,s+2);
    dfs(r+1,s-2);
    dfs(r-1,s+2);
    dfs(r-1,s-2);
}
int main()
{
    //freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    for(int k=1; k<=t; k++)
    {
        a=0;
        memset(flag,0,sizeof(flag));
        scanf("%d%d",&m,&n);
        printf("Scenario #%d:\n",k);
        dfs(0,0);
        int f=1;
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                if(flag[i][j]==0) f=0;
        if(!f) printf("impossible\n");
        else
        {
            for(int i=0; i<a; i++)
                printf("%c%c",arr[i].p,arr[i].q);
            printf("\n");
        }
    }
    return 0;
}

      结果不尽人意,果断被系统判了WA。debug调试一次后,我就明白了自己错在哪里。走到错误的路的时候,虽然搜索的进度会返回,但是flag已经标记,没有被改回来,所以后续搜索的时候会误以为此处已经在整条路径中。于是我就改用了回溯法。在走到错路的时候,返回时把flag还原回去,然后在dfs函数参数里加了路径的下标,这样保证每次存储的时候都是正确的路(就算前面存的是错误的回溯之后会重新赋值)。修改后,我的代码如下

#include <stdio.h>
#include <memory.h>
#include <string.h>
#define maxn 30

typedef struct road
{
    char p;
    char q;
} T;
T arr[700];
int flag[maxn][maxn],m,n,a=0,success=0,vis[2][8]= {{-2,-2,-1,-1,1,1,2,2},{-1,1,-2,2,-2,2,-1,1}};
void dfs(int x,int y,int a)
{
    if(success)  return;
    arr[a].p=x+'A';
    arr[a].q=y+'1';
    if(a==m*n)
    {
        success=1;
        return;
    }
    int yy,xx;
    for(int i=0; i<8; i++)
    {
        xx=x+vis[0][i];
        yy=y+vis[1][i];
        if(flag[xx][yy]==1) continue;
        if(yy<0||yy>=m||xx<0||xx>=n) continue;
        flag[xx][yy]=1;
        dfs(xx,yy,a+1);
        flag[xx][yy]=0;
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    for(int k=1; k<=t; k++)
    {
        a=0;
        memset(flag,0,sizeof(flag));
        scanf("%d%d",&m,&n);
        printf("Scenario #%d:\n",k);
        success=0;
        flag[0][0]=1;
        dfs(0,0,1);
        if(!success) printf("impossible\n");
        else
        {
            for(int i=1; i<=m*n; i++)
                printf("%c%c",arr[i].p,arr[i].q);
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}
    一次AC。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值