【问题标题】:Recursion if Condition条件递归
【发布时间】:2016-03-31 12:09:37
【问题描述】:

以下是来自 spoj 的问题的实现:- http://www.spoj.com/problems/COINS/

#include <stdio.h>

#define ll long long

ll arr[100000];

ll max(ll n)
{
    if(n < 49999)// Doubt
    {
        if(!arr[n])
            return arr[n] = max(n/2) + max(n/3) + max(n/4);
        else
            return arr[n];
    }
    else
        return max(n/2) + max(n/4) + max(n/3);
}


int main()
{
    ll n, c = 0, i;

    for(i = 0; i < 12; i++) // Also why 12 when the input can be <12
    {
        arr[i] = i;
    }

    while(scanf("%lld", &n) != EOF)
    {
        printf("%lld\n", max(n));

    }

    return 0;
}

为什么if条件包含n

【问题讨论】:

  • @SouravGhosh 为什么是 49999?
  • 我建议您取 50000 并手动计算出您的阵列中会发生什么。
  • 49999 似乎没有理论上的理由。它也可能是 99999。
  • 我认为制作程序的人广泛使用了像gdb 这样的调试器,然后硬编码了那些神奇的值或限制(不管你想怎么称呼它):\
  • 为什么要用#define ll long long 语句来隐藏代码?代码应该写得尽可能清楚。代码中ll的实例没有写清楚代码

标签: c if-statement conditional-statements dynamic-programming


【解决方案1】:

据我所知,

编写代码的人,不知怎的,他发现(手动)如果 硬币小于 12 则结果将是它本身。以便他使用 12.
(查看输入硬币的解释 = 2)

关于递归函数

我们知道我们不能声明大小为 1,000,000,000 的数组,所以他尝试 使用他可以创建数组的其他值(此处为 49999) 然后在数组中取硬币的结果,如 arr[12] = 13 (其中 12 是硬币,13 是结果)这样他就可以得到结果 不使用带有 arr[12] 的数组生成值(仅) 硬币 12。

希望你能理解。

【讨论】:

  • 奇怪的是,问题中的数组大小为 100,000,但代码中的测试将其使用限制为 100,000 个元素中的前 49,999 个。这可能是编辑的意外——部分原因是没有使用enum#define 值作为数组大小,或者没有使用sizeof(arr)/sizeof(arr[0]) 作为数组中的元素数。还有一个 'off-by-one' 元素:如果数组的大小为 50,000,则限制应为 &lt; 50000 而不是 &lt; 49999
【解决方案2】:

除了前 20 多个值以及最大值和最小值之外,没有检查每种可能性:

我的期望是

arr[] 中的前 12 个条目是预先计算的,以帮助减少递归的深度,但是美元值与前 12 个条目的计算值不同。

对于硬币值

这个限制值 (49999) 可以扩展到 100000,因为这是 arr[] 数组的可用大小。

预设和保存到 arr[] 数组是为了帮助减少执行时间和递归深度。

数组的使用使得任何先前计算的值(在发布的代码中,最多为 49999)可以立即由 max() 函数返回,而无需进一步递归。

为了更好的文档和健壮性以及更快的执行,我会稍微修改代码如下:

#include <stdio.h>
#include <stdint.h>

#define MAX_ARRAY_LEN (100000)

uint32_t arr[ MAX_ARRAY_LEN ] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

uint32_t max(uint32_t n)
{
    if(n < MAX_ARRAY_LEN)
    { // value of 'n' within the range of the learning array arr[]

        if(!arr[n] && n)
        { // then learning array arr[] not yet set
            return arr[n] = max(n/2) + max(n/3) + max(n/4);
        }

        else
        { // else learning array arr[] already set for 'this' value of 'n'
            return arr[n];
        }
    }

    else
    { // value of 'n' is greater than the learning array arr[]
        return max(n/2) + max(n/4) + max(n/3);
    }
} // end function: max


int main( void )
{
    uint32_t n;

    int status;
    while( (status = scanf("%u", &n)) == 1 && EOF != status)
    {
        if( 1000000000 >= n)
        {
            printf("%u\n", max(n) );
        }

        else
        {
            printf(" invalid value entered, must be in the range 0...1 000 000 000\n");
        } // end if
    } // end while

    return 0;
} // end function: main

【讨论】:

  • 为什么你认为拥有 3 美元硬币的人可以在 1:1 兑换 3 美元的情况下只能从中获得 2 美元?对于每枚价值低于 12 的硬币,他们通过简单地直接转换来获得最大交换,如问题中的代码中所实现的那样。如您正确显示的那样,对于价值 12 的硬币,他们可以获得 ⎣12/2⎦ + ⎣12/3⎦ + ⎣12/4⎦ = 13。
  • 我对这个新答案进行了修改,根据 SPOJ,它是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-20
  • 2023-03-31
  • 1970-01-01
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多