尝试解决Bytelandian gold coins
上的问题spoj
,并且要求是动态编程,我真的想了解并讨论解决方案。主要是reference variable r
。为何使用map STL
? map
如何减少努力?
#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;
}
答案 0 :(得分:0)
这是使用 memoization 递归的常用习惯用法。我们的想法是,对Coin(n)
的每个值,最多应调用n
一次。第一次调用它时,我们应该计算该值然后将其存储在某个地方,这样第二次调用它时,我们只返回存储的值而不是再次进行递归计算。
地图用于存储先前计算的值。你不能使用数组,因为它太大了。数组使用与其最大索引成比例的空间,而地图仅使用与其包含的键值对数量成比例的空间。
参考是一个可爱的伎俩。使用特定值Coin
调用n
函数后,有两种可能性:
行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;
}