• poj2488 A Knight's Journey


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

    题目大意:骑士厌倦了一遍又一遍地看到同样的黑白方块,于是决定去旅行。

    世界各地。当一个骑士移动时,他走的是“日”字。骑士的世界是他赖以生存的棋盘。我们的骑士生活在一个棋盘上,它的面积比普通的8 * 8板要小,但它仍然是矩形的。你能帮这个冒险的骑士制定旅行计划吗? 找到一条路,这样骑士每一次都能到每一个广场。骑士可以在棋盘的任何方格上开始和结束。输入从第一行的正整数n开始。下面的行包含n个测试用例。每个测试用例由一个带有两个正整数p和q的单行组成,其中1 <= p * q <= 26。这表示一个p * q棋盘,其中p描述了多少个不同的数1,…p存在,q描述存在多少个不同的字母。这些是拉丁字母表中的第一个q字母:A,…每个场景的输出从包含“Scenario #i:”的一行开始,其中i是从1开始的场景的数量。然后打印一行一行,其中包含了字母顺序的第一路径,它访问棋盘上的所有方块,然后是空行。通过将访问的方块的名称连接起来,可以在一行中给出路径。每个方名称由大写字母和数字组成。

    如果不存在这样的路径,那么您应该在一行上输出impossible的内容。

    也就是说横坐标时是字母(向右为正),纵坐标是数字(向下为正),骑士需要走完全图的方格,并找出包含了字母顺序的第一条路径,那么这就暗示了骑士的起点坐标一定是A1,只有是按字母排序第一个一定是A1。骑士走的是“日”字,那么根据字母排序骑士的横坐标和纵坐标减少或增加的遍历顺序是8个方向(-2,-1)(-2,1)(-1,-2)(-1,2)(1,-2)(1,2)(2,-1)(2,1),这样的遍历顺序,得到的第一条路径一定是按字母顺序的路径。

    算法思想:回溯法,问题的解空间树是一颗八叉树,分别对应八个方向,设置相应的剪枝函数,1)如果出界,舍弃相应子树;2)如果找到了一条路径(一定是按字母排序的路径),用一个isSoluted记录,如果问题解决,则减去相应子树;3)我们可以用visited[ ][ ]记录该方格被访问,减去相应子树(重复走回路),并在回溯时设为未访问。

     1 #include <cstring>//使用memset()
     2 #include <iostream>
     3 using namespace std;
     4 //按字典排序的行走方向       8叉树
     5 const int dx[8] = { -2, -2, -1, -1, 1, 1, 2, 2 };
     6 const int dy[8] = { -1, 1, -2, 2, -2, 2, -1, 1 };
     7 const int N = 27;
     8 bool visited[N][N];//判断方格是否被访问
     9 struct step {//走路的记录
    10     char x, y;
    11 };
    12 step path[N];//记录路径的
    13 bool isSoluted;//能否走通
    14 int cases, p, q;//记录案例数,p行123... q列ABC...
    15 void Backtrade(int x, int y, int t)//x 和 y 为当前坐标 t为深度
    16 {
    17     path[t].x = x + 'A' - 1;   //转为 char 记录走的路径
    18     path[t].y = y + '0';
    19     if (t == p * q)//如果有一条路走完全部 则可解 直接退出回溯
    20     {
    21         isSoluted = true;
    22         return;
    23     }
    24     for (int i = 0; i < 8; i++)
    25     {
    26         int nx = x + dx[i];
    27         int ny = y + dy[i];
    28         //剪枝函数 出界 或 已访问过 或 问题已解决 不进入相应子树
    29         if (0 < nx && nx <= q && 0 < ny && ny <= p&& !visited[nx][ny] && !isSoluted)
    30         {
    31             visited[nx][ny] = true;
    32             Backtrade(nx, ny, t + 1);
    33             visited[nx][ny] = false;//回溯时撤回标记
    34         }
    35     }
    36 }
    37 int main()
    38 {
    39     cin>>cases;
    40     for (int c = 1; c <= cases; c++)
    41     {
    42         isSoluted = false;
    43         cin >> p >> q;
    44         memset(visited, false, sizeof(visited));
    45         visited[1][1] = true;    //从第一个字典序起点开始走
    46         Backtrade(1, 1, 1);
    47         cout<<"Scenario #"<<c<<":"<<endl;
    48         if (isSoluted)
    49         {
    50             for (int i = 1; i <= p * q; i++)
    51                 cout << path[i].x << path[i].y;
    52             cout << endl;
    53         }
    54         else
    55             cout<<"impossible"<<endl;
    56         cout << endl;
    57     }
    58     return 0;
    59 }
    作  者: Angel_Q 出  处:http://www.cnblogs.com/DA799422035/ 关于作者:如有问题或建议,请多多赐教! 版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。 特此声明:所有评论都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。 声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是作者坚持原创和持续写作的最大动力!
  • 相关阅读:
    P3387 【模板】缩点 tarjan
    P2831 愤怒的小鸟 状压dp
    交流帖
    P3959 宝藏 模拟退火。。。
    B1060 [ZJOI2007]时态同步 dfs
    P1850 换教室 概率dp
    树链刨分(待修改)
    B3403 [Usaco2009 Open]Cow Line 直线上的牛 deque
    B3402 [Usaco2009 Open]Hide and Seek 捉迷藏 最短路
    B5248 [2018多省省队联测]一双木棋 状压dp
  • 原文地址:https://www.cnblogs.com/DA799422035/p/8994075.html
Copyright © 2020-2023  润新知