以下代码中发生了什么?请有人解释每一行

时间:2014-01-28 05:41:43

标签: c++ stl dynamic-programming

尝试解决Bytelandian gold coins上的问题spoj,并且要求是动态编程,我真的想了解并讨论解决方案。主要是reference variable r。为何使用map STLmap如何减少努力?

#include<iostream>
#include<map>
using namespace std;
unsigned Coin(unsigned n)
{
    unsigned & r = m[n];
    if(r)
        return r;
    unsigned s=(n/2)+(n/3)+(n/4);
    if(s>n)
        return r = Coin(n/2)+Coin(n/3)+Coin(n/4);
    return r = n;
}

int main()
{
    cin>>n;
    cout<<Coin(n)<<endl;
    return 0;
}

2 个答案:

答案 0 :(得分:0)

这是使用 memoization 递归的常用习惯用法。我们的想法是,对Coin(n)的每个值,最多应调用n一次。第一次调用它时,我们应该计算该值然后将其存储在某个地方,这样第二次调用它时,我们只返回存储的值而不是再次进行递归计算。

地图用于存储先前计算的值。你不能使用数组,因为它太大了。数组使用与其最大索引成比例的空间,而地图仅​​使用与其包含的键值对数量成比例的空间。

参考是一个可爱的伎俩。使用特定值Coin调用n函数后,有两种可能性:

  1. 该值已存储在地图中,因为我们已经计算了它
  2. 该值尚未存储在地图中,但它将在我们完成时完成,因为我们总是希望在计算后立即存储值,因此我们不必计算它第二次。
  3. unsigned & r = m[n];初始化r以引用存储的值(如果有)。如果没有,则键<{1}}插入到地图中,然后使n成为对该值的引用。在身体的其余部分,我们可以计算答案并将其存储在r中。这将自动更新存储在地图中的值。

答案 1 :(得分:0)

这是一个动态编程问题,如果你不知道,请检查http://en.wikipedia.org/wiki/Dynamic_programming

动态编程的想法是缓存结果,以便稍后的确切调用将在O(1)/ O(lg n)时间内完成。但我怀疑这个程序是否完整,我找不到变量m(这是一组)声明行。

这个问题的公式是 硬币(n)=最大值(最大值(n / 2 + n / 3 + n / 4,硬币(n / 2)+硬币(n / 3)+硬币(n / 4)),n)

#include<iostream>
#include<map>
using namespace std;
unsigned Coin(unsigned n)
{
    unsigned & r = m[n];             //see if the value is computed
    if(r)
        return r;                    //if computed, return the computed value.
    unsigned s=(n/2)+(n/3)+(n/4);    
                    //if not, find out the max profit for coin with r on it.
    if(s>n)
        return r = Coin(n/2)+Coin(n/3)+Coin(n/4);
                    //if conversion can make a profit, make the profit
                    //Coin(p) >= p => Coin(n/2)+Coin(n/3)+Coin(n/4) >=n/2+n/3+n/4

    return r = n;   //if not, do not do the conversion
}

int main()
{
    cin>>n;
    cout<<Coin(n)<<endl;
    return 0;
}