【问题标题】:Converting C++ function to recursive function将 C++ 函数转换为递归函数
【发布时间】:2020-03-18 12:27:20
【问题描述】:

我正在查看一个函数,需要将其转换为动态编程形式。但是我很难理解这个函数中使用的逻辑(基本情况是什么?),这个函数的原作者不再可以提问,我不能对他的工作做出正面或反面,而且有0 个可用文档。

说明:

此函数接受一个正整数矩阵,并通过以下方式找到最大和 从矩阵的每一列中选择一个元素,从左到右移动。当你穿过 矩阵逐列,总和会受到惩罚,具体取决于您的方式 相对于您之前的两个位置移动。如果您选择的下一行在前两行之间 选定的行,没有惩罚;但是,对于上面的每一行,您的总和将被罚款 2 前两个中的最大值或低于前两个中的最小值。

int calSum(int row, int cols, vector<vector<int>> inputArray, vector<int> *outputArray){

    int ans[row][cols][row];
    int index[row][cols][row];

    int firstCol[row];

    for(int i=0;i<row;i++){

        firstCol[i]= inputArray[i][0] - 2*(i);
    }

    for(int i=0;i<row;i++){

        for(int j=0;j<row;j++){
            int penalty;

            if(i<=j){
                penalty=0;
            }else{
                penalty= 2* (i-j);
            }

            ans[i][1][j]= inputArray[i][1] - penalty+ firstCol[j];

        }
    }

    for(int j=2;j<cols;j++){

        for(int i=0;i<row;i++){


            int nextRow= i;

            for(int k=0;k<row;k++){

                int currRow= k;
                int ind=-1;
                int maxVal= INT_MIN;
                for(int l=0;l<row;l++){

                    int prevRow=l;
                    int max1= max(prevRow, currRow);
                    int min1= min(prevRow, currRow);

                    int penalty;
                    if(nextRow<=max1&&nextRow>= min1){
                        penalty=0;
                    }else if(nextRow>max1){
                        penalty= 2*(nextRow-max1);
                    }else{
                        penalty= 2*(min1-nextRow);
                    }

                    int val= -penalty+ inputArray[i][j] + ans[k][j-1][l];
                    if(val>maxVal){
                        maxVal=val;
                        ind=l;
                    }
                }

                ans[i][j][k]=maxVal;
                index[i][j][k]=ind;

            }

        }

    }

    int max=INT_MIN;
    int x=-1;
    int y=-1;

    for(int i=0;i<row;i++){

        for(int j=0;j<row;j++){

            if(ans[i][cols-1][j]>max){
                max= ans[i][cols-1][j];
                x=i;
                y=i;
            }

        }
    }

    for(int j=cols-1;j>=2;j--) {

        outputArray->push_back(x);
        int temp=x;
        x= y;
        y= index[temp][j][y];
    }

    outputArray->push_back(x);
    outputArray->push_back(y);

    return max;

}

我已经尝试过跟踪代码并一直迷失在逻辑中。非常感谢您对此函数所做的基本解释。

【问题讨论】:

  • 问题是什么?您需要解释此功能的工作原理吗?什么是“动态表单”?
  • 请注意,variable-length arrays(例如 ansindex)不在 C++ 中。请改用std::vector
  • @Someprogrammerdude 这是我在查看代码时非常困扰的事情。我知道 C++ 不支持 VLA,但作者以某种方式在这里使用了它们 - 我选择暂时忽略它,因为我对代码本身没有问题,我更关心弄清楚这个函数中使用的逻辑.
  • 一些编译器(咳 GCC 咳)把它作为一个不可移植的扩展。这就是为什么我总是尽可能地禁用扩展。
  • 问题陈述不完整:前两列有惩罚吗?

标签: c++ algorithm recursion optimization dynamic-programming


【解决方案1】:

核心数据结构ans 的工作方式如下:ans[i][j][k] 是从(k, 0)(i, j) 的最佳路径。 (注意这里使用 row,col 表示法来匹配程序中的表示法)

如果我们通过for循环遍历代码:

  • 第一个 for 循环计算第一列中值的得分,同时考虑到行 > 1 的所有内容都有惩罚。
  • 在给定起始行 j 和结束行 i 的情况下,第二个 for 循环计算 ans[i][1][j] 或到第二列的最大路径。
  • 第三个for循环逐渐向右扩展ans。对于j &gt; 1 的每一列,它通过找到一个使 (k, 0) 到 (l, j-1) 到 (i, j) 的 l 来填充 ans[i][j][k]。第一部分可以从ans[k][j-1][l]读取,最后一步根据问题给出的规则计算。

    这个循环还将l的最优选择写入ind数据结构中,因此您可以稍后重建最优路径。

  • 第四个 for 循环只是找到最大路径值并存储结束行。
  • 最终的 for 循环通过追溯 ind 数据结构中的步骤来重构路径。

【讨论】:

    猜你喜欢
    • 2023-04-05
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-08
    • 2015-05-30
    相关资源
    最近更新 更多