递归方法不断崩溃(更改算法)

时间:2011-04-27 22:40:25

标签: c++ algorithm recursion

//amt = amount of cents to get change for
//onhand = array of available coins . Ex: {3, 0, 1, 0} = 3 quart, 0 dime, 1 nickel, 0 pennies

//denoms = {25, 10, 5, 1}

//ndenoms = 4 ; i.e the number of different denominations

// thechange = array of change. Ex: if amt = 80, then one possible thechange = {3, 0, 1, 0} b/c 3*25 + 1*5 = 80 cents



int i = 0;

void makechange(int amt, int *onhand, int *denoms, int ndenoms, int *thechange)
   {            

      if ( (denoms[i] * onhand[i]) > amt)
         {
                    onhand[i]--;    // # of coins is too much, decrement and try again
                    makechange(amt, onhand, denoms, ndenoms, thechange); // try agan
         }

      thechange[i] = onhand[i]; //found #of coins

      amt = amt - denoms[i]*onhand[i]; // get remaining amount from change
      i++;

      if (amt != 0) // we're not done with change so move on to next denomination
      {
           makechange(amt, onhand, denoms, ndenoms, thechange);
      }   


      else if (amt == 0) // we're done with the change so all the other # coins = 0
      {
           for (int j = i; j < amt; j++)
             {
              thechange[j] = 0;
             }
      }




   }   






Now, down in main when I actually call the function prototype and print out the result

//


makechange(amt, onhand, denoms, ndenoms, thechange);

  for (int k = 0; k < ndenoms; k++)
  {
      cout << thechange[i] << " ";
  }


//

我收到错误。

这个算法对我来说似乎很明智,有人知道它为什么会一直崩溃吗?

我在这里正确使用了递归吗?

3 个答案:

答案 0 :(得分:1)

如果您拨打makechange两次,则第二次无效,因为全局变量i将出错。

如果您尝试makechange并且手头没有足够的变化来制作它会怎么样?

同样如果你有3个季度和3个角钱,并被要求变化80美分会发生什么?你的算法将使用所有3个季度,然后卡住。

答案 1 :(得分:0)

你是说

吗?
for (int k = 0; k < ndenoms; k++) { cout << thechange[k] << " "; }

通过使用全局变量i来实现一个小错字。

      for (int j = i; j < amt; j++) { thechange[j] = 0; }

我认为你的意思是

for (int j = i; j < ndenoms; j++)

取决于amt的最终值,这将导致您运行数组的末尾,从而导致崩溃。

你可以更轻松地解决这个问题,而无需递归。您是否需要使用递归进行分配?如果没有,试试这个:

int makechange(int amt, int *onhand, int *denoms, int ndenoms, int *thechange)
{
for (int i=0; i < ndenoms && amt > 0; i++) { while (onhand[i] > 0 && denoms[i] <= amt) { onhand[i]--; // use one coin thechange[i]++; amt -= denoms[i]; } } return amt; // this is the amount you owe if you dont have enough on hand }

答案 2 :(得分:0)

我做了shsmith提到的更改,这里是修改完整的c ++程序。

#include <iostream> 

using namespace std;

int i = 0;

void makechange(int amt, int *onhand, int *denoms, int ndenoms, int *thechange)
{
    if ( (denoms[i] * onhand[i]) > amt)
    {
            onhand[i]--;    // # of coins is too much, decrement and try again
            makechange(amt, onhand, denoms, ndenoms, thechange); // try agan
    }

    thechange[i] = onhand[i]; //found #of coins
    amt = amt - denoms[i]*onhand[i]; // get remaining amount from change
    i++;
    if (amt != 0) // we're not done with change so move on to next denomination
    {
            makechange(amt, onhand, denoms, ndenoms, thechange);
    }
    else if (amt == 0) // we're done with the change so all the other # coins = 0
    {
            for (int j = i; j < ndenoms; j++)
            {
                    thechange[j] = 0;
            }
    }}

int main(){

    //Now, down in main when I actually call the function prototype and print out the result
    int amt = 80, onhand[] = {3, 0, 1, 0}, denoms[] = {25, 10, 5, 1}, ndenoms = 4, thechange[4];
    makechange(amt, onhand, denoms, ndenoms, thechange);
    for (int k = 0; k < ndenoms; k++)
    {
            cout << thechange[k] << " ";
    }
    cout << "\n";
    return 0;}

此代码在我的机器上运行完美。我用Cygwin编译了它。

注意:此算法仅在您更多或正确使用面额硬币时才有效。如果没有足够数量的硬币,那么递归方法就没有退出,因为'amt'永远不会变为零。与此同时,你永远不会检查'i'值是否在'ndenoms'的范围内。这也可能导致超出边界的错误,这可能导致程序错误地退出。