如何在c中解决具有许多不同级别(它们是递归的)的问题

时间:2012-04-25 11:11:45

标签: c algorithm recursion

我想知道如何处理问题,其中有一个过程用于c的问题的许多不同“级别”,最好是以“惯用”的方式。我知道我没有解释得这么好,让我举一个例子:

考虑制作游戏求解器的一般问题,它应该打印出最佳的下一步。我认为它应该检查for循环中所有可能的移动并查看它是否是一个成功的移动(在如果是这样的话,返回移动,否则检查对手可以对抗你的移动(for loop)的所有可能移动并调用该函数再次找到最佳移动。

但是,我发现这种方法有一些局限性,例如性能(程序会花费时间运行调用函数所需的样板代码等) 并且灵活性有限,因为该函数必须找到一种方法来与调用者进行通信,发现移动有多好。也就是说,如果它可以完成的话。

bestmove()
{
  for (;i<maxmove;i++)
   {
    if(checkifwinning(moves[i])) return;
    for (;n<maxopponentmove;n++)
     {
      bestmove();
     }
   }

我一直在和haskell搞乱一段时间,所以我担心我的想法是寻求递归解决方案。我希望你能告诉我一种以'c native'方式编写这个函数的方法。 / p>

3 个答案:

答案 0 :(得分:3)

C语言允许递归函数。但是,它没有尾递归调用的概念(但在某些情况下,最近的GCC编译器能够将一些尾递归调用优化为纯迭代的机器代码)。

编码递归函数时,应避免过于递归和太大的本地调用帧(因此请使用堆内存)。

答案 1 :(得分:0)

我认为你真正需要的是branch-and-bound类算法:保持一个“开放”动作列表(即尚未考虑)和一个“闭合”动作列表(即已经考虑过)。在C中,最好实现具有两个队列(打开和关闭)。那么你将得到如下算法:

while (open is not empty)
{
   pop gameState from open
   if (gameState in closed)
      continue;
   push gameState to closed
   for (eachMove)
   {
       computeNewState();
       addStateToOpen();
   }
}

与递归方法相比,这有几个优点:

  • 您确定每个游戏状态仅被视为一次
  • 你没有“压倒”堆栈

答案 2 :(得分:0)

您正在谈论搜索游戏树以寻找最佳动作;你可以使用像minimax这样的标准算法。你的方法似乎是树的深度优先搜索,终止于第一个获胜的移动;请注意,这不会找到获胜动作的最短路径,也不会防止对手获胜。

有很多方法可以加快搜索游戏树,例如alpha-beta pruning。这样的标准算法是要走的路 - 比担心在C等中调用函数的开销要好得多.C函数调用并不昂贵。在编写C代码时要小心这种“优化” - 无论如何,优化器在这些事情上可能会更好。至少,首先以最直接的方式编写一个版本,这样你就可以对其进行基准测试。你的工作是找到一个好的算法。