当前位置: 首页 > 知识库问答 >
问题:

在国际象棋骑士巡回赛中遇到困难

韦睿
2023-03-14

我试着用回溯法为骑士之旅问题编写代码。我的代码适用于4x4矩阵,但对于8x8矩阵,它不会在输出屏幕上显示任何内容。

我不知道我做错了什么。

我的代码就是这样工作的:

如果所有的广场都参观过

print the solution

其他的

>

  • 向solution vector添加下一步动作之一,并递归检查该动作是否会导致解决方案。(一个骑士最多可以走八步。我们在这一步的八步中选择一步)。

    如果在上述步骤中选择的移动没有导致解决方案,则从解决方案向量中删除此移动,然后尝试其他替代移动。

    如果所有替代方案都不起作用,则返回false(返回false将删除递归中先前添加的项,如果通过递归的初始调用返回false,则“不存在解决方案”)

    以下是我写的代码:

    #include<iostream>
    using namespace std;
    #define n 8
    int safe(int c[n][n],int i, int j)
    {
        if((i>=0&&i<n)&&(j>=0&&j<n))
        {
         if(c[i][j])
          return 0;
         else 
          return 1;
        }
        return 0;
    }
    
        int knightstour(int c[n][n],int i,int j,int k)
      {
          if(k==n*n)
         {
          for(i=0;i<n;i++)
          {
              for(j=0;j<n;j++)
                 cout<<c[i][j]<<"  ";
               cout<<endl;     
           }
           return 1;
          }
         else
         {
           c[i][j]=k;
              if(safe(c,i+2,j+1))
              {
                  if(knightstour(c,i+2,j+1,k+1))
                    return 1;
              }
    
              if(safe(c,i+2,j-1))
              {
                  if(knightstour(c,i+2,j-1,k+1))
                    return 1;
              }
    
              if(safe(c,i-2,j+1))
              {
                  if(knightstour(c,i-2,j+1,k+1))
                    return 1;
              }
    
              if(safe(c,i-2,j-1))
              {
                  if(knightstour(c,i-2,j-1,k+1))
                    return 1;
              }
    
              if(safe(c,i+1,j+2))
              {
               if(knightstour(c,i+1,j+2,k+1))
                 return 1;
               }
    
              if(safe(c,i-1,j+2))
              {
               if(knightstour(c,i-1,j+2,k+1))
                 return 1;
              }
    
              if(safe(c,i+1,j-2))
              {
               if(knightstour(c,i+1,j-2,k+1))
                 return 1;
              }
    
              if(safe(c,i-1,j-2))
              {
               if(knightstour(c,i-1,j-2,k+1))
                 return 1;
              }
    
            c[i][j]=0;
            return 0;
          }
       }
      int main()
     {
       int c[n][n]={0};
       if(!knightstour(c,0,0,0))
       cout<<"solution doesn't exist";
       return 1;
     }
    
  • 共有1个答案

    云欣嘉
    2023-03-14

    让我们暂时假设您的算法是正确的,因为它似乎产生了至少对n==6有用的东西:

     0  13  20  23  34  11  
    21  30  35  12  19  24  
    14   1  22  31  10  33  
    29   4   7  16  25  18  
     6  15   2  27  32   9  
     3  28   5   8  17  26  
    

    以下是使用不同的n值运行代码的时钟时间结果:

    ===== 1  0m  0.001s
    ===== 2  0m  0.001s
    ===== 3  0m  0.003s
    ===== 4  0m  0.002s
    ===== 5  0m  0.070s
    ===== 6  0m 35.997s
    ===== 7  ...
    

    你会注意到,我还没有n=7的数字,它仍然在运行,在5.5小时后开始计数:-)

    因为它将持续至少那么长时间(大约330分钟),我们可能可以使用回归分析计算8号的最小数字(使用仅使用5号、6号和尚不完整的7号的数据的二次多项式)(a)。根据这些计算,这一最低数字约为16.5小时。

    然而,即使它不是二次的,对于6x6的板,它跳到了36秒,对于7x7,它跳到了(至少)5.5小时,这意味着你使用的算法不能很好地扩展。所以你可能会发现它正在工作,你可能只需要等一会儿。可能很长一段时间:-)

    (a)如果你感兴趣(或者想检查/批评我的方法),这是我的分析。警告:数学超前...

    我们有数据集:

    x (value of n)   y (seconds taken)
    --------------   -----------------
          5                 0.07
          6                36.00
          7               600.00 (when it had been running ten minutes)
    

    使用以下公式:

    y = ax^2 + bx + c
    

    我们得到联立方程:

      0.07 = 25a + 5b + c (1)
     36    = 36a + 6b + c (2)
    600    = 49a + 7b + c (3)
    

    减去配对可以得到:

    (2) - (1):  35.93 = 11a + b (4)
    (3) - (2): 564    = 13a + b (5)
    
    (5) - (4): 528.07 = 2a
    

    所以a=264.035。将其替换回(5),得到b=-2868.455,将ab替换为(3),得到c=7741.47。将这三个值放入方程(1)(2)(3)中,得到了期望值。

    这是我高中时使用的方法,但是,当然,如果有一个快速而肮脏的Python程序,当600图形发生变化时,该程序可以快速工作,这样做会更好:

    import sys
    
    y5 = 0.07 ; y6 = 36 ; y7 = int(sys.argv[1]) * 60
    
    a = ((y7 - y6) - (y6 - y5)) / 2
    b = (y7 - y6) - 13 * a
    c = y7 - 49 * a - 7 * b
    
    y8 = 64 * a + 8 * b + c
    print(y8, y8 / 3600)
    

    你只需运行它,提供7号的当前值,它就会推出最小值(以秒和小时为单位)。

     类似资料:
    • 我正在尝试编写一个骑士之旅算法,它有两个数组,访问和板。ACCESS是我用来判断下一步是什么的数组,board是用户将看到的最终结果的数组。我的算法通过检查找到可用移动次数最少的正方形,然后到达那里。如果恰好有两个可能的移动,并且可用的移动次数相同,我会找到哪一个离中心最远(离边界最近),然后移动到该点。这个算法应该会一直提供一个完美的64步骑士巡演程序,但我通常只得到大约60步,有人能告诉我为什

    • 我制作了这段代码来完成骑士之旅,你必须和一个没有重复的骑士一起到达棋盘上的每一个方块,但我有一些问题。它只会打印一个没有移动的空棋盘,我不知道如何修复它。 测试人员: 如果您有任何建议,我将不胜感激,我正在为一门课做这件事,所以我需要尽快完成。

    • DreamChess 是一款开放源码、跨平台(可在 Windows、Mac OS X 及 Linux 上运行)的 3D 国际象棋游戏。该游戏包含自身的引擎 Dreamer,提供各种国际象棋棋盘,并具有背景音乐及声效等其他附属功能。

    • 我对我的象棋游戏的最小极大算法的实现有问题。它的大部分似乎都起作用了,但它要么从来没有做出好的动作,要么对它们的评估(基于两个玩家的活动棋子的分数)出了问题。例如,如果我设置了check(例如,傻瓜的伴侣),ai会做一些随机的事情,而不是杀死国王。我真的找不出我做错了什么。 评估电路板的类StandardBoardEvaluator在经过一些测试后似乎可以工作,因此问题很可能出现在MiniMax实

    • 我已经有一个Board对象,包含一个碎片列表。Piece是一个抽象类,有一个位置(x,y)和一个颜色(黑色或白色)。然后是King、Queen、Knight这三个类,实现了Piece类。 谢谢