这是一个我无法解决的考试问题,我需要解决它,因为我可以在下一次考试中面对它(它决定你是否得到D或A)。
问题: “两个机器人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)
起始盒数为34
这意味着我们是 的 DONE 强> 当所有的盒子都消失了,我们也在 的 无效 强> 如果我们剩下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 ); } }
你可以看到它很短。这是递归解决方案中常见的一个功能。另一个是需要一些练习来包裹你的头。看 这里有一个更简单的例子 ,收集 TextBoxes 来自表单中的嵌套容器!
TextBoxes
我们来测试吧!这是一个测试平台,它运行许多箱号的代码,并向控制台写出每个起始号码可获得多少解决方案。最后一个起始编号(34)的解决方案也写入a TextBox 。
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();
这是控制台输出:
可以通过8种方式移动10个盒子。 11个盒子可以移动6个 方法。 可以通过11种方式移动12个盒子。 可以移动13个盒子 以18种方式。 14个盒子可以16种方式移动。 15盒即可 以36种方式移动。 16个盒子可以36种方式移动。 17盒 可以用58种方式移动。 18个盒子可以86种方式移动。 19 盒子可以98种方式移动。 可以在172个移动20个盒子 方法。 21个盒子可以201种方式移动。 可以移动22个盒子 以304方式。 可以以432种方式移动23个盒子。 24盒可以 以549种方式移动。 可以以856种方式移动25个盒子。 26 盒子可以以1088种方式移动。 可以在1587年移动27个盒子 方法。 28个盒子可以2220种方式移动。 29箱即可 以2966种方式移动。 30个盒子可以4364种方式移动。 31 盒子可以5798种方式移动。 可以在8284中移动32个盒子 方法。 33箱可以11529种方式移动。 34盒即可 以15760的方式移动。
Maje肯定会收集输出 Stringbuilder ;创建 15k 字符串是昂贵的,并直接添加到一个 TextBox 拿一个 的 真实长 强> 时间..
Stringbuilder
15k
的 奖金*问题: 强>