C++ 动态规划中的核心转储错误
我正在修改一个程序,该程序可以确定给定数量的零钱所需的最少硬币数量。这种硬币系统只有三枚硬币:$0.01、$0.06、$0.10。所以13美分,如果硬币是3的话,最小的数字是3。对于56美分,最小数字是6,等等。程序做这部分,我的部分是回溯备忘录表以确定使用的每个硬币的数量。例如,13美分的最低值是3枚硬币,这些硬币是2枚6美分的硬币和1枚1美分的硬币 下面生成的备注表如下所示:C++ 动态规划中的核心转储错误,c++,dynamic-programming,memoization,C++,Dynamic Programming,Memoization,我正在修改一个程序,该程序可以确定给定数量的零钱所需的最少硬币数量。这种硬币系统只有三枚硬币:$0.01、$0.06、$0.10。所以13美分,如果硬币是3的话,最小的数字是3。对于56美分,最小数字是6,等等。程序做这部分,我的部分是回溯备忘录表以确定使用的每个硬币的数量。例如,13美分的最低值是3枚硬币,这些硬币是2枚6美分的硬币和1枚1美分的硬币 下面生成的备注表如下所示: 1cent 0 1 2 3 4 5 6 7 8 9 10 11 12 13 6cent 0 1 - 3 - -
1cent 0 1 2 3 4 5 6 7 8 9 10 11 12 13
6cent 0 1 - 3 - - - 2 - - - - - 3
10cent 0 - - 3 - - - - - - - - - 3
对于这样的事情,我们总是从右下角开始。我试图递归地做这件事。我注意到一种模式。如果我们有一个数字,而上面的数字不是同一个数字,那么我们“跳”到同一行的左边cent
空格。所以在最下面的一行,10美分,在最后我们看到从13跳到3,也就是10个空格。如果一个数字和上面的数字是同一个数字,这意味着硬币在多次使用后停止使用,我们向上移动一行。因此,在上表中,我们从右下角开始,3
。正上方的数字也是一个3
,因此,由于出现了0次“跳跃”,因此使用的10美分硬币的数量是0,我们向上移动到下一行,即6美分
行
现在我们比较3
和13
。这两个数字不相等,所以我们在6
空间上移动。因此,我们现在有了1
“跳跃”。现在我们来看2
和7
。这两个也不相等,所以我们移动了6
更多的空间,现在我们有了2
“跳跃”。现在我们比较1
和1
,它们相等,所以我们向上移动一行,从该点开始。由于过去这一行中有2
“跳跃”,因此使用的6美分
硬币数量为2
。最后一部分让人困惑。当我们向上移动一行时,我们从同一列开始。由于我们比较了1
和1
,我们将从该专栏继续。因为这是最后一行,行0
,所以剩余的更改量将始终是顶部的数字。在我的例子中,我们上移了一行,从1
开始,因此使用的1美分
硬币的数量是1
。这意味着使用的硬币总数为:
1 cent: 1
6 cent: 2
10 cent: 0
我知道这是一个非常混乱的措辞。希望我的代码能更好地显示这一点。下面是我如何尝试实现这一点的:
void countCoins( uint i, uint a, uint coinVal,
const vector< uint > & denom,
Matrix< uint > & memo )
{
uint numCoins = 0;
// Check the current value with the value above it
if( memo.at(i, a) != memo.at(i - 1, a) )
{
if( denom.at(i) == coinVal )
{
numCoins++;
}
countCoins( i, a - denom.at(i), coinVal, denom, memo ); // If not equal, "jump" over
}
else
{
if( i > 0 )
{
countCoins( i - 1, a, coinVal, denom, memo ); // If equal, move up a row
}
else
{
numCoins += a; // If equal and the row number is 0
}
}
}
void countCoins(uint i、uint a、uint coinVal、,
常量向量&denom,
矩阵(备忘录)
{
uint numCoins=0;
//检查当前值及其上方的值
if(memo.at(i,a)!=memo.at(i-1,a))
{
如果(在(i)处的名称=coinVal)
{
numCoins++;
}
countCoins(i,a-denom.at(i),coinVal,denom,memo);//如果不相等,“跳过”
}
其他的
{
如果(i>0)
{
countCoins(i-1,a,coinVal,denom,memo);//如果相等,则上移一行
}
其他的
{
numCoins+=a;//如果相等且行号为0
}
}
}
这段代码可以编译,但当我运行它时,会收到一条消息,上面写着:“matrix.h:48:Object&matrix::at(uint,uint)[with Object=unsigned int;uint=unsigned int]:断言'rowmemo
和/或denom
之前,您需要检查I
和a
是否小于0
void countCoins( uint i, uint a, uint coinVal,
const vector< uint > & denom,
Matrix< uint > & memo )
{
if (i < 0) {
// handle edge case and return
}
if (a < 0) {
// handle edge case and return
}
uint numCoins = 0;
...
...
}
void countCoins(uint i、uint a、uint coinVal、,
常量向量&denom,
矩阵(备忘录)
{
if(i<0){
//处理封边盒并返回
}
if(a<0){
//处理封边盒并返回
}
uint numCoins=0;
...
...
}
注意:如果
i
和a
的值可能高于memo
和denom
的大小,则还需要检查该值。但是在你的代码中,你似乎总是在减少它们,所以情况可能不是这样 我很难理解您的逻辑,但是您的行或列的索引值是否可能在某个点为负或为空?请编辑您的问题并包括一个。是的,我确信我的逻辑很难理解。这在我的脑海里很有道理,但解释起来很难。我试着输入调试语句来打印行和列的索引,它们似乎是正确的。对于每个单元格,您需要记录最小硬币数和用于到达它的硬币数。然后你可以从任何选择的面额开始,沿着桌子走回去。