• poj 2488 A Knight's Journey(暴力dfs 你懂的)


    http://poj.org/problem?id=2488

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

    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

    分析:
    这里 1 <= p * q <= 26 题目数据量不是很大,可以直接暴力dfs求解,主要是保证输出第一个为最小字典序,这里我们控制遍历搜索时的顺序就可以了,这里主要体现在以下数组中:
    int cy[]={-2,-2,-1,-1,1,1,2,2};
    int cx[]={-1,1,-2,2,-2,2,-1,1};
    这里cy数组的值为 {-2,-2,-1,-1,1,1,2,2} 因为cy为 输出串中的 A,B,C 故优先选择,然后cx {-1,1,-2,2,-2,2,-1,1} 一小一大的排列
    这样就可以保证最小字典序
    代码:
     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 
     5 using namespace std;
     6 
     7 //这样设置这两个数组很好的保证了最后输出的序列是字典序
     8 int cy[]={-2,-2,-1,-1,1,1,2,2};
     9 int cx[]={-1,1,-2,2,-2,2,-1,1};
    10 
    11 int mark[30][30];
    12 int flag=0;
    13 
    14 void dfs(int n,int m,int x,int y,int cnt)
    15 {
    16     int i,j,k;
    17     if(flag)  //序列找到便不用在找
    18     {
    19         return;
    20     }
    21     if(cnt==n*m)  //找到序列进行输出
    22     {
    23         for(k=1;k<=n*m;k++)
    24         for(i=1;i<=n;i++)
    25         {
    26             for(j=1;j<=m;j++)
    27             {
    28                 if(k==mark[i][j])
    29                 {
    30                     printf("%c%d",'A'-1+j,i);
    31                 }
    32             }
    33         }
    34         printf("\n");
    35         flag=1;  //标记表示序列
    36         return;
    37     }
    38     for(i=0;i<8;i++)
    39     {
    40         int dx=x+cx[i];
    41         int dy=y+cy[i];
    42         if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&!mark[dx][dy])
    43         {
    44             mark[dx][dy]=cnt+1;  //标记这点的位置状态
    45             dfs(n,m,dx,dy,cnt+1);  //进行下一个点的查找
    46             mark[dx][dy]=0;  //回溯
    47         }
    48     }
    49 }
    50 
    51 int main()
    52 {
    53     int t,k;
    54     scanf("%d",&t);
    55     for(k=1;k<=t;k++)
    56     {
    57         int n,m;
    58         scanf("%d%d",&n,&m);
    59         printf("Scenario #%d:\n",k);
    60         if(n==1&&m==1)
    61         {
    62             printf("A1\n\n");
    63             continue;
    64         }else if(n==1||m==1)
    65         {
    66             printf("impossible\n\n");
    67             continue;
    68         }
    69         memset(mark,0,sizeof(mark));
    70         int i,j;
    71         for(i=1;i<=n;i++)
    72         {
    73             for(j=1;j<=m;j++)
    74             {
    75                 mark[i][j]=1;
    76                 flag=0;
    77                 dfs(n,m,i,j,1);
    78                 if(flag)
    79                 {
    80                     break;
    81                 }
    82                 memset(mark,0,sizeof(mark));
    83             }
    84             if(j<=m)
    85             {
    86                 break;
    87             }
    88         }
    89         if(i>n)
    90         {
    91             printf("impossible\n");
    92         }
    93         printf("\n");
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    11g 配置 dgmgrl 以及报错 DataGuard ORA-00313,
    java三种匿名的方式开启线程
    java 四种方式实现字符流文件的拷贝对比
    java中过滤查询文件
    通过Java实现斗地主
    java中Map的entrySet 和keySet的使用
    python3列表推导式和生成器。
    python的特殊方法总结
    python3 定义向量运算
    python3模拟扑克牌
  • 原文地址:https://www.cnblogs.com/crazyapple/p/3109179.html
Copyright © 2020-2023  润新知