动态规划算法问题C++和Python实现时结果的差异?

Posted

技术标签:

【中文标题】动态规划算法问题C++和Python实现时结果的差异?【英文标题】:The difference in results when the dynamic planning algorithm problem C++ and Python are implemented? 【发布时间】:2020-04-27 02:12:42 【问题描述】:

在绝地求生者中,盔甲和防弹衣分为三个等级,分别记录为1,2,3。每次只能捡起自己没有的,或者把低等级的装备升级到高等级,问一下从无到有到“护甲3级防弹甲3级护甲”有多少升级路线?当前状态由有序数量的对(防弹衣,盔甲)表示,两者的值都为 0-3,例如(0,0)->(0,1)->(0,3)->(3,3) 作为升级策略。

理论上是4*4的数组,不知道为什么python可以实现4*4的数组,但是c++必须写成int[4][4]即5*5的数组结果是对,int[3][3] 计算错误? (结果是最后一个元素,也就是106)

蟒蛇:

dp = [[1,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
for i in range(4):
    for j in range(4):
        for m in range(j):
            dp[i][j] += dp[i][m]
        for m in range(i):
            dp[i][j] += dp[m][j]
dp

输出:106(正确答案) c++:

#include<iostream>
int dp[3][3];
int main ()
    dp[0][0] = 1;
    for (int i = 0; i <= 3; i++)
        for (int j = 0; j <= 3; j++)
            for (int m = 0; m < i; m++)
                dp[i][j] += dp[m][j];
            for (int m = 0; m < j; m++)
                dp[i][j] += dp[i][m];
       
    
  std::cout<<dp[3][3]<<std::endl;

输出:1495(worng!但我不知道为什么?为什么 c++ 中的输出错误?)

【问题讨论】:

快速回答——C++ 和 Python 是两种不同的语言。这就像问为什么法语有 3 个重音符号,而西班牙语有一个。 您的 C++ 代码具有未定义的行为,因为 result 应该返回一个 int 但它永远不会返回。很明显,两个程序中最里面的两个循环是不同的。 【参考方案1】:

好的,找到了。您的问题是您使用大小为 3x3 的数组,就好像它大小为 4x4。 一个工作版本:

#include<iostream>

int dp[4][4];
int main ()

    dp[0][0] = 1;
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            for (int m = 0; m < j; m++)
                dp[i][j] += dp[i][m];
            for (int m = 0; m < i; m++)
                dp[i][j] += dp[m][j];
       
    
    std::cout<<dp[3][3]<<std::endl; 

重要的变化是 int dp[3][3];int dp[4][4];。这样,您上面的代码就可以工作了。 没有它,您会越界访问数组,这是未定义的行为。 1495 只是编译器如何解释您的代码的结果,但由于它是 UB,因此任何结果都是有效的。这就是 UB 的欺骗性 - 它通常看起来像是在做一些合理的事情,让它看起来像是你的算法中的一个错误,而实际上并非如此。 我在实验时做了一些进一步的小改动。一种是切换两个内部 for 循环,但那一个不是必需的。我还将&lt;= 3 更改为&lt; 4,因为这是更常见的样式,但显然也不需要。

为了将来,熟悉使用调试器,或在步骤之间打印出您的结果。如果你有工作的 phyton 代码,你可以在那里做同样的事情,然后比较两个程序的行为。但是请注意,在您的情况下,结果可能看起来很奇怪 - 我在实验时这样做了,结果很有趣,请参阅 http://www.cpp.sh/8aufco 。尽管循环将变量 i 限制为 3,但变量 i 运行到 257。我不知道为什么会这样 - 只是 UB 的结果。

您可能需要考虑将原始数组更改为 std::vectorstd::array,但我暂时保留了它。 您的 main 应该 return 0; 作为一个好的做法,尽管它可以按原样工作。 您不应该在 C++ 中使用任何全局变量,就像使用 dp 一样。只需在您的 main(或您以后使用它的任何地方)中声明它。全局变量是错误的一个简单来源(注意常量很好)。

【讨论】:

非常感谢,我发现我犯了一个愚蠢的错误。感谢您提供这些规范和建议,再次感谢您 @zhuowei 不要把它称为愚蠢的错误。看起来更像是你忽略的东西。一直发生在我身上。这样的东西很难调试,我偶然发现了它。

以上是关于动态规划算法问题C++和Python实现时结果的差异?的主要内容,如果未能解决你的问题,请参考以下文章

详细实例说明+典型案例实现 对动态规划法进行全面分析 | C++

C++ 不知算法系列之深入动态规划算法思想

算法设计与分析--求最大子段和问题(蛮力法分治法动态规划法) C++实现

算法袋鼠过河,动态规划问题(C++源码)

动态规划算法入门练习 (python实现)

C++ 不知算法系列之初识动态规划算法思想