【问题标题】:c 8 coins combination code [closed]c 8个硬币组合码[关闭]
【发布时间】:2017-04-20 22:09:17
【问题描述】:

我的代码应该计算总组合。使用这些硬币支付 1-500 美元之间的现金:1、2、5、10、20、50、100、200。但它计算不正确。我做错了什么? 您可以假设输入是正确的,并且您只能使用循环和 if 语句。你不能使用递归。

int pr, a, b, c, d, e, f, g,h, poss = 0;
printf_s("What is the amount that you like to check? (or press '0' to exit)\n");
scanf_s("%d", &pr);

for (a = 0; a <= pr; a++)
{
    for (b = 0; b <= (pr/2); b++)
    {
        for (c = 0; c <= (pr /5); c++)
        {
            for (d = 0; d <= (pr /10); d++)
            {
                for (e = 0; e <= (pr /20); e++)
                {
                    for (f = 0; f <= (pr / 50); f++)
                    {
                        for (g = 0; g <= (pr / 100); g++)
                        {

                            for (h = 0; h <= (pr/200); h++)
                            {
                                if (1 * a + 2 * b + 4 * c + 10 * d + 20 * e + 40 * f + 100 * g + h * 200 == pr)

                                    poss += 1;

                            }
                        }
                    }
                }
            }
        }
   }printf_s("The number of possibilities is: %d.\n", poss);
}

【问题讨论】:

  • 结果如何?您的程序是否多次打印它?
  • printf 语句移出循环后,输入100 需要一秒钟才能报告6118。输入 200 需要 45 秒才能报告 104342。所以我的猜测是 500 将持续到明天,这个数字将超出 int 的范围。

标签: c loops for-loop combinations


【解决方案1】:

当输入5 时,会报告正确的权限数,但扩展代码会打印错误的值。因为这一行

if (1 * a + 2 * b + 4 * c + 10 * d + 20 * e + 40 * f + 100 * g + h * 200 == pr)

有错误的面额。应该是

if (1 * a + 2 * b + 5 * c + 10 * d + 20 * e + 50 * f + 100 * g + h * 200 == pr)

你也应该移动这条线

printf_s("The number of possibilities is: %d.\n", poss);

在循环之外。

【讨论】:

    【解决方案2】:

    您的最终printf 需要脱离循环

        for (a = 0; a <= pr; a++)
        {
            for (b = 0; b <= (pr/2); b++)
            {
                for (c = 0; c <= (pr /5); c++)
                {
                    for (d = 0; d <= (pr /10); d++)
                    {
                        for (e = 0; e <= (pr /20); e++)
                        {
                            for (f = 0; f <= (pr / 50); f++)
                            {
                                for (g = 0; g <= (pr / 100); g++)
                                {
    
                                    for (h = 0; h <= (pr/200); h++)
                                    {
                                        if (1 * a + 2 * b + 4 * c + 10 * d + 20 * e + 50 * f + 100 * g + h * 200 == pr)
    
                                            poss += 1;
    
                                    }
                                }
                            }
                        }
                    }
                }
           }
        }
        printf("The number of possibilities is: %d.\n", poss);
    

    【讨论】:

    • tnx 适用于所有助手。当用户按 0 时,我如何立即关闭程序?
    【解决方案3】:

    正如Weather Vane 回答中提到的,OP 在内部条件中使用了一些错误的乘数(4 和 40 而不是 5 和 50)。

    值得注意的是,即使使用这种蛮力方法,我们也可以通过避免在(过于嵌套的)循环内进行不必要的计算并将这些循环的范围限制在更小的范围内,从而节省一些 CPU 时间。 考虑以下重构:

    #include <stdio.h>
    
    int number_of_possibilities(int price)
    {
        int poss = 0;
    // It takes less time to consume the bigger pieces earlier    
        for ( 
    // 'a' represent the sum of the values of 200$ pieces, not the number of 200$
    // pieces, which is 'a / 200'           
              int a = 0; a <= price;
    // add the value of a single 200$ piece to move forward
              a += 200 )
        {
          for ( int b = 0,
    // 'dif_b' is what is left from the price, once the 200$ pieces are counted
                    dif_b = price - a;
    // we don't need to iterate from 0 to 'price', but only to what is left
                b <= dif_b; b += 100 )                
          {
    // 'dif_c' is what is left once the 100$ and 200$ pieces counted so far are
    // subctracted from the original price. The same holds for the inner loops     
            for ( int c = 0, dif_c = dif_b - b; c <= dif_c; c += 50 )
            {
              for ( int d = 0, dif_d = dif_c - c; d <= dif_d; d += 20 )
              {
                for ( int e = 0, dif_e = dif_d - d; e <= dif_e; e += 10 )
                {
                  for ( int f = 0, dif_f = dif_e - e; f <= dif_f; f += 5 )
                  {
                    for ( int g = 0, dif_g = dif_f - f; g <= dif_g; g += 2 )
                    {
    // now that only the 1$ coins are left to consider, we can avoid another inner
    // loop and just realize that we need exactly 'dif_g - g' 1$ coins to pay the 
    // full price, so there is one and only one possible combination.
                      ++poss;
                    }
                  }
                }
              }
            }      
          }
        }
        return poss;
    }
    
    
    int main(void)
    {
        printf("  i   number of possibilities\n\n");
        for ( int i = 0; i < 501; ++i )
        {
            printf("%4d %16d\n", i, number_of_possibilities(i));
        }
        return 0;
    }
    

    这给出了以下内容:

      i   number of possibilities
    
       0                1
       1                1
       2                2
       3                2
       4                3
       5                4
       6                5
       7                6
       8                7
       9                8
      10               11
    
     ...
    
      99             4366
     100             4563
     101             4710    
    
     ...
    
     498          6159618
     499          6224452
     500          6295434
    

    在 1.6 GHz 的旧 Atom N270 上执行不到 2 秒...

    【讨论】:

    • tnx 很匹配,对了,有没有自动chk输入的程序?
    • @תהילהואוריאיבגי 您可以先查看this answer。这个网站上有很多关于这个主题的资源。
    • 你能解释一下你在循环中做了什么吗?例如: (...dif_a = price - a; b
    • @תהילהואוריאיבגי 请查看更新的(带有解释性 cmets)代码。
    猜你喜欢
    • 1970-01-01
    • 2012-11-28
    • 1970-01-01
    • 2015-12-22
    • 2016-03-28
    • 1970-01-01
    • 2016-09-13
    • 2011-08-19
    • 1970-01-01
    相关资源
    最近更新 更多