最短的路径与船上的数字

时间:2012-05-27 23:05:58

标签: c++ path figures shortest

我的家庭作业(C ++)遇到了麻烦。我不是要求完整的解决方案,但向正确方向倾斜可能会有所帮助。 :)

我有一块NxN板(最大N = 100)和一块1x2的数字(立方体)。立方体的一面涂成红色,另一面涂成蓝色。立方体的默认位置是左上角,蓝色朝上:

B B . .
. . . .
. . . .
. . . .

(4x4例子,B代表蓝色)

黑板上可能有石块(障碍物)。 我可以用我的身材做出动作:

  • 顺时针旋转90/180/270度
  • 你可以围绕它的右/左/上/下边缘翻转立方体,改变它的''向上颜色''

例如,在默认位置使用右转:

. . R R
. . . .
. . . .
. . . .

然后使用rotate 90:

. . R .
. . R .
. . . .
. . . .

然后使用左翻:

. B . .
. B . .
. . . .
. . . .

当然,旋转或翻转时,你不能落在石头上。 因此,问题是 - 对于任何给定的电路板配置(图形位置和石头位置),编写一个程序,将“立方体回家”置于默认位置(蓝色方向上!)使用最小数量的移动并在可能的情况下返回1,如果不可能则返回0。

我觉得这个问题很有意思,但我不得不承认我对它有点困惑。特别是蓝色侧/红色侧面部分。我无法弄清楚如何“翻译”那些我可以在通常的最短路径算法语言中使用的动作(我从未使用过任何这些)。 所以,我很感激你能给出的每一条建议! :)

3 个答案:

答案 0 :(得分:1)

首先,由于要求您找到确切的最佳路径,我会选择Dijksta's algorithm

对于此算法,您需要:

  1. 给下一个的功能 可能的举动。
  2. 告诉您某个职位是否已经存在的功能 访问。
  3. 告诉您每条路径的总费用的功能。
  4. 当然还有一个功能,告诉你何时到达决赛 位置
  5. 给定初始位置,您的立方体可以准确到达7个新位置。很容易选择哪些是可能的。

    G只是你到目前为止所做的动作数量+ 1为下一步动作:)

    我会使用哈希表来跟踪访问位置。 (这可能是最难写的功能),但你现在不需要过度思考。一个简单的向量和一个逐项比较就可以了。您可以在代码运行后对其进行优化。

    最后,您需要检查立方体是否处于蓝色方向的初始位置。

答案 1 :(得分:1)

您可以将每个可能的1x2块和颜色(红色或蓝色)组合解释为顶点并作为边缘移动。如果可以在一次移动中从某个其他组合到达特定的1x2块和颜色组合(顶点),则在这两个组合之间存在连接(边缘)。然后你必须在结果图中找到给定配置和“home”配置之间的最短路径(可能是广度优先搜索,因为无论你执行什么移动,移动的成本都是相同的。)

如果想要更进一步,你可以使用在图遍历期间使用启发式的高级图搜索算法(启发式是在黑板上没有障碍物时到达目的地所需的最小移动量)。例如,您可以使用A* algorithm

答案 2 :(得分:0)

在处理此类问题时,首先要做的是找到问题的状态的表示。 在这种情况下,您需要:

  1. 表示图形左上角位置的两个整数
  2. 一个布尔值,表示图形的颜色(红色/蓝色)
  3. 一个布尔值,表示图形的方向(水平/垂直)
  4. 如果您熟悉位掩码,则应该只使用32位整数(x位置为8位,y位置为8位,其余为2位)。 这样,您就不需要实现比较运算符。 您可以使用这3个信息定义一个简单的结构(称之为state),并对此进行严格排序比较(只需将state放入std::set

    在此之后,您可以使用BFS解决此问题。

    要做到这一点,你需要:

    1. std::map<state,state>用于存储您在密钥中已访问过的位置,以及您来自该值的位置(如果您可以使用c ++ 11,则将map替换为unordered_map并使用位掩码存储您的状态)
    2. 一个std::queue<state>,其中按下并弹出要处理的状态。
    3. 确定从给定状态可到达的每个可能状态的一些代码(即实现所有可能的移动,处理电路板尺寸)
    4. 伪代码:

         map<state,state>  visited;
         queue<state> to_be_processed;
      
         visited.insert( initial_state,initial_state); //you are not coming from anywhere
         to_be_processed.push ( initial_state);
      
         while(!to_be_processed.empty()) {
      
                    state cur = to_be_processed.pop();
                    if ( cur == end_state) //you are done
                    {
                          //to get the path from initial_state to end_state you have just to walk visited in the inverse order.
                          return 1;
                    }
                    for ( i = every possible state reachable from cur) {
                          if (visited.count(i) != 0) continue; //already visited
                          to_be_processed.push(i);
                          visited.insert(i,cur); //i has been visited, and you reached i from cur
                    }
      
         }
         return 0; //if you get here, no way
      

      障碍的存在使问题更难以编码,但在概念上并没有不同。

      请注意,在这种情况下,BFS可以正常工作,因为您从一个州到另一个州的费用总是相同的。