机器人移动箱子

时间:2016-09-25 16:05:44

标签: c# robot

这是一个我无法解决的考试问题,我需要解决它,因为我可以在下次考试时再次面对它(它决定你是否得到D或A)。

问题:

  

"两个机器人R1和R2在工厂周围携带盒子。 R1可以同时携带1或3或5个盒子,而R2可以同时携带2个或4个盒子。如果有34个盒子,写一个C#程序,找到机器人R1和R2的每个移动组合,携带所有盒子。移动的方式是一个机器人可以在另一个机器人之后移动(R1获取盒子,将它们带到所需的目的地,然后R2可以进入下一个)。还显示哪种组合允许以最小的移动携带所有盒子。

     

可能的组合:(R1 = 5,R2 = 4),(R1 = 3,R2 = 4),(R1 = 3,R2 = 2),(R1 = 3,R2 = 2),(R1 = 3) ,R2 = 2),(R1 = 1,R2 = 2)"

问题在于我甚至不知道从哪里开始。我写了一些可能的组合,希望我可以从某处开始获得线索。我尝试了一个程序,但它没有工作(打印盒子的数量,直到从机器人中取出的盒子数量不是负数:box-(r1 + r2)> = 0,这是一个特定的每种可能的组合中的情况)

我找到了一位来自年龄较大的学生的程序,该程序向我发送了以下窗体代码:

            private void button1_Click(object sender, EventArgs e)
    {
        int Min = 34;
        string stMin = "";
        for(int i1=0;i1<=34;i1++)
            for (int i2 = 0; i2 <= 34; i2++)
                for (int i3 = 0; i3 <= 34; i3++)
                    for (int j1 = 0; j1 <= 34; j1++)
                        for (int j2 = 0; j2 <= 34; j2++)
                            for (int j3 = 0; j3 <= 34; j3++)
                            {
                                if (i1 * 3 + i2 * 4 + i3 * 5 + j1 * 1 + j2 * 2 + j3 * 3 == 34 && i1 > 0 && i2 > 0 && i3 > 0 && j1 > 0 && j2 > 0 && j3 > 0 && (i1 + i2 + i3 == j1 + j2 + j3))
                                {
                                    if(i1+i2+i3+j1+j2+j3<Min)
                                    {
                                        Min = i1 + i2 + i3 + j1 + j2 + j3;
                                        stMin = "R1 =>" + i1 + " x 3, " + i2 + " x 4 " + i3 + " x 5 " + "R2 =>" + j1
                                            + " x 1 " + j2 + " x 2 " + j3 + " x 3 "; 
                                    }
                                    string st = "R1 =>" + i1 + " x 3, " + i2 + " x 4 " + i3 + " x 5 " + "R2 =>" + j1
                                            + " x 1 " + j2 + " x 2 " + j3 + " x 3 ";
                                    listBox1.Items.Add(st);
                                }
                                listBox1.Items.Add("==========Min=========");
                                listBox1.Items.Add(stMin);
                            }
    }

我分析了它3天但我不知道这段代码是如何工作的。问他解释,但他说这不是他的代码,不记得他得到它的地方,也不知道它是否有效。 我也问了朋友和同事,但没有人知道如何解决它。

如果有人可以给我一个想法或一段代码来开始解决方案,我将不胜感激(编写完整的代码会很棒,而且我不会将它复制粘贴到我的考试中,我会看最多了解代码的每一步)。
旁边信息:我是新手程序员。我的教授给我们提供了基本的东西,比如从用户那里读取输入,使用循环和创建类。我的自学并没有达到如此复杂的问题,所以请尽可能深入和具体地解释你的解决方案。

提前谢谢

1 个答案:

答案 0 :(得分:2)

好吧,既然你仍然好奇我们就解决了这个问题。

这是一个经典的,与往常一样,第一件事是要非常清楚条件:

  • 这些可能的组合:(R1 = 5,R2 = 4),(R1 = 3,R2 = 4),(R1 = 3,R2 = 2),(R1 = 3,R2 = 2 ),(R1 = 3,R2 = 2),(R1 = 1,R2 = 2)

  • 起始盒数为34

这意味着当所有方框都消失时我们已完成,如果我们剩下1或2个方框,我们也会处于无效组合移动中,因为这些我们的任何组合都无法移动。

让我们接下来创建一个很好的数据结构来保存允许的组合,这样我们就可以在循环中使用它;让我们称那些'完全移动'

Dictionary<string, int> fullMoves = new Dictionary<string, int>();

我们会将移动存储为字符串,并且还会存储每个组合移动的框的总数。

接下来我们需要填写数据结构:

for (int i = 1; i <= 5; i += 2)
    for (int j = 2; j <= 4; j += 2)
        fullMoves.Add(i + "-" + j + "  ", i + j);

使用调试器测试它,看看它是否有效!

现在让我们开始做生意:我们需要一个功能来完成真正的工作。

正如我在评论中所解释的,这是递归解决方案的典型问题。所有的选择都会创建一条路径树(即完整移动的序列),树(几乎)总是要求递归的方法。它将一遍又一遍地召唤自己,将目前的状况传递出去,直到完成,即已达到“暂停状态”。

抽象的目标是:

  • 测试情况,如果是的话
    • 无效,丢弃它
    • 完成后,添加到解决方案列表
    • 未完成:正常工作(添加新选项)并重复所有当前路径

这是一段代码就是这样做的。它传递了当前路径列表和到目前为止找到的正确解决方案。此外,新路径和方框数仍然存在。

void moveBoxes(int count, string curMove, List<string> curMoveList, List<string> solutions)
{
    // test for halting conditions:
    // 1) count == 0: we're done with this solution
    if (count == 0)
    {
        solutions.Add(curMove);
        return;
    }
    // 2) less than three boxes: invalid solution:
    else if (count < 3)
    {
        curMoveList.Remove(curMove);
        return;
    }
    // keep moving..:
    foreach (string cm in curMoveList)
        foreach (string k in fullMoves.Keys)
        {
            int bc = count - fullMoves[k];
            moveBoxes( bc, curMove + k,  curMoveList, solutions );
        }
}

你可以看到它很短。这是递归解决方案中常见的一个功能。另一个是需要一些练习来包裹你的头。查看here for a simpler example,它从表单中的嵌套容器中收集TextBoxes

让我们来测试吧!这是一个测试平台,它运行许多箱号的代码,并向控制台写出每个起始号码可获得多少解决方案。最后一个起始编号(34)的解决方案也写为TextBox

List<string> solutions = new List<string>();
List<string> curMoveList = new List<string>();
for (int ccc = 10; ccc <= 34; ccc++)
{
    solutions = new List<string>();
    curMoveList = new List<string>(); 

    int count = ccc;
    curMoveList.Add("");

    moveBoxes(count, "", curMoveList, solutions);

    Console.WriteLine(ccc + " boxes can be moved in " + solutions.Count + " ways.\r\n");
}
StringBuilder sb = new StringBuilder();
foreach (string s in solutions) sb.Append(s.Length / 5 + " moves:  " + s + "\r\n");
textBox1.Text = sb.ToString();

这是控制台输出:

  

10个盒子可以8种方式移动。
11个盒子可以移动6个   方式。
12个箱子可以11种方式移动.1箱子可以移动   18种方式.14个盒子可以16种方式移动.15个盒子可以   以36种方式移动.16个箱子可以36种方式移动.17箱   可以58种方式移动。
可以86种方式移动18个盒子   箱子可以98种方式移动.21个箱子可以移动172个   方式.21箱可以201个方式移动.21个箱子可以移动   304方式.23箱可以432个方向移动.24箱可以   以549种方式移动.25箱可以856种方式移动。
26   箱子可以1088个方式移动。左边有27个箱子可以移动   方式。
28箱可以2220个方式移动.29箱可以   以2966种方式移动.21箱可以4364种方式移动   箱子可以5798种方式移动.21箱子可以在8284移动   方式。
33箱可以11529种方式移动.34箱可以   以15760种方式移动。

Maje肯定会收集Stringbuilder的输出;创建15k字符串非常昂贵,并将它们直接添加到TextBox,需要真正的长时间。

加分*问题:

  • 为什么我最后除以5? - )
  • 为什么解决方案的数量总是在增加? - )