在有限的空间内进行记忆

时间:2013-03-06 19:24:42

标签: c++ map memoization stdmap

在尝试提高this contest答案的速度时,我有一个函数,它接受两个值nk并产生一个输出。重复计算,所以我要记住它。我不能使用2D数组,因为nk的约束是10^5!所以我正在使用地图:

std::map<std::pair<int,int>,double> m;

double solve(int n, int k)
{
    if(k==0) return n;
    if(k==1) return (n-1)/2.0;

    std::pair<int,int> p = std::make_pair(n,k);
    std::map<std::pair<int,int>,double>::iterator it;

    if( (it=m.find(p)) != m.end())
        return it->second;

    double ans = 0;
    for(int i=1 ; i<=n-1 ; i++)
        ans += solve(i,k-1);
    ans = ans/n;
    m[p] = ans;

    return ans;
}

但显然,这种做法太慢了。我的记忆有问题吗?或者我可以获得像数组一样的恒定时间提取而不是从地图中进行对数提取吗?

此函数解决了这种重现:

formula

f(x,0) = xf(x,1) = (x-1)/2

能以更好的方式解决这个问题吗?非常感谢。

2 个答案:

答案 0 :(得分:2)

小改进:记住find和dereference返回的迭代器,而不是使用operator []。

答案 1 :(得分:0)

您不必存储二维数组值。而不是记忆,转而解决问题,而是使用动态编程。

为节省时间,请注意f(x, y) = 0 x <= y

f(i, 0)计算1 <= i <= x - k的值并将它们存储到一维数组中。然后为f(i, 1)计算2 <= i <= x - k + 1,为f(i, 2)计算3 <= i <= x - k + 2,依此类推,直到f(i, k - 1)k <= i <= x - 1为止。然后你可以计算f(x, k)。在每个步骤中,您只需要两个长度为x - k的数组。

计算f(i, j)需要增加i - j - 1个分区。所以总时间是Θ((x-k) 2 k)。但是如果你先计算和然后除以它会更快,因为每个和只是比前一个更多的一个元素,所以总时间是Θ((x - k)k)。