跟踪递归调用的最简单方法是什么?

时间:2017-04-20 07:46:51

标签: c++ recursion dynamic-programming

我写了一个问题的递归DP解决方案。对于某些测试用例,解决方案是失败的(它只是过度计数或计数不足一次)。如何仅追溯或打印导致我最终答案的状态?

递归函数是这样的。它需要4个输入。如果之前已经评估过某个特定状态,它将从std::map返回解决方案,否则会对其进行评估。解决方案以递归方式返回每个州的min值。

这是尝试解决Play the Dragon

Google CodeJam 2017 1A
int hd,ad,hk,ak,b,d;
int inf=1e9+1;
map< tuple<int,int,int,int>, int > dp;

int count(int hld, int hlk, int atd, int atk){
  if(dp[make_tuple(hld,hlk,atd,atk)]){
    return dp[make_tuple(hld,hlk,atd,atk)];
  }
  else{
    if(hlk<=0){
      return 0;
    }
    if(hld<=0){
      return inf;
    }
    if(hlk-atd<=0){
      return 1;
    }
    if(hld==hd-atk){
      if(b==0||d==0){
        if(b==0&&d!=0){
          return dp[make_tuple(hld,hlk,atd,atk)] = 1 + min(
                                                           count(hld-atk,hlk-atd,atd,atk),
                                                           count(hld-atk+d,hlk,atd,(atk-d)<0?0:(atk-d))
                                                           );
        }
        if(b!=0&&d==0){
          return dp[make_tuple(hld,hlk,atd,atk)] = 1 + min(
                                                           count(hld-atk,hlk-atd,atd,atk),
                                                           count(hld-atk,hlk,atd+b,atk)
                                                           );
        }
        return dp[make_tuple(hld,hlk,atd,atk)] = 1 + count(hld-atk,hlk-atd,atd,atk);
      }
      return dp[make_tuple(hld,hlk,atd,atk)] = 1 + min(
                                                       count(hld-atk,hlk-atd,atd,atk),
                                                       min(
                                                           count(hld-atk,hlk,atd+b,atk),
                                                           count(hld-atk+d,hlk,atd,(atk-d)<0?0:(atk-d))
                                                           )
                                                       );
    }
    if(b==0||d==0){
      if(b==0&&d!=0){
        if(atk<=0){
          return dp[make_tuple(hld,hlk,atd,atk)] = 1 + count(hld-atk,hlk-atd,atd,atk);
        }
        return dp[make_tuple(hld,hlk,atd,atk)] = 1 + min(
                                                         count(hld-atk,hlk-atd,atd,atk),
                                                         min(
                                                             count(hd-atk,hlk,atd,atk),
                                                             count(hld-atk+d,hlk,atd,(atk-d)<0?0:(atk-d))
                                                             )
                                                         );
      }
      if(b!=0&&d==0){
        return dp[make_tuple(hld,hlk,atd,atk)] = 1 + min(
                                                         count(hld-atk,hlk-atd,atd,atk),
                                                         min(
                                                             count(hld-atk,hlk,atd+b,atk),
                                                             count(hd-atk,hlk,atd,atk)
                                                             )
                                                         );
      }
      if(atk<=0){
        return dp[make_tuple(hld,hlk,atd,atk)] = 1 + count(hld-atk,hlk-atd,atd,atk);
      }
      return dp[make_tuple(hld,hlk,atd,atk)] = 1 + min(
                                                       count(hld-atk,hlk-atd,atd,atk),
                                                       count(hd-atk,hlk,atd,atk)
                                                       );
    }

    if(atk<=0){
      return dp[make_tuple(hld,hlk,atd,atk)] = 1 + min(
                                                       count(hld-atk,hlk-atd,atd,atk),
                                                       count(hld-atk,hlk,atd+b,atk)
                                                       );
    }
    return dp[make_tuple(hld,hlk,atd,atk)] = 1 + min(
                                                     count(hld-atk,hlk-atd,atd,atk),
                                                     min(
                                                         count(hld-atk,hlk,atd+b,atk),
                                                         min(
                                                           count(hd-atk,hlk,atd,atk),
                                                           count(hld-(atk-d)<0?0:(atk-d),hlk,atd,(atk-d)<0?0:(atk-d))
                                                         )
                                                         )
                                                     );
  }
}

2 个答案:

答案 0 :(得分:0)

一种简单的方法是将父元组与计算值保持在一起,即如果T是你的元组,则使用std::map <T, std::pair<int, T>>

答案 1 :(得分:0)

我认为你的愿望可以有一个解决方案,但它并不简单,实现它你可以在你的代码中引入比现在更多的问题或错误(我建议他们的存在,因为你没有实现正确回答)。我们的想法是使用唯一的id标记任何新的函数调用,并将数据存储在全局某处。调用该函数时,它应具有有关其父ID的信息,并创建自己的id以传递给它将调用的所有分支。完成后,将其id写入父ID数据单元格并显示结果。您在函数中只有一个位置用于分支 - 当您计算两个计数的最小值时。所以你需要在父id数据单元中输入带有id的调用结果,以便在将来的analasys中进行比较。因此,您创建了一个调用结构,它本身就没有信息。主要的是向父id添加一些额外的信息 - 选择哪个分支(我meand,你有15个返回语句和2个选择变体 - 我想你想知道选择了什么)。对于任何选择的分支你和id字段选择标志。通过这个标志,当你的计算结束时,你将从id到id throght你的数据并在屏幕上只写“选择”的数据。祝你好运!