递归解决方案的动态编程解决方案

时间:2014-09-21 19:40:27

标签: c++ algorithm recursion dynamic-programming

给定输入n,找到所有可能的数字组合1 ... n的总和。 例如,如果n=3,那么所有可能的组合都是

(1),(2),(3),(1,2),(1,3),(2,3),(1,2,3)

他们的总和是

1 + 2 + 3 + (1+2) + (1+3) + (2+3) + (1+2+3) =24

我可以使用recursion解决此问题。如何使用Dynamic Programming解决此问题?

#include<iostream>
using namespace std;
int sum=0,n;
int f(int pos,int s)
{
    if(pos>n)
    {
        return 0;
    }
    else
    {
        for(int i=pos+1;i<=n;++i)
        {
            sum+=s+i;
            f(i,s+i);
        }
    }
}
int main()
{
     cin>>n;
     sum=0;
     f(0,0);
     cout<<sum<<'\n';

    }
}

修改 虽然使用此series可以在恒定时间内解决此问题。

但我想知道如何使用Dynamic Programming完成此操作,因为我对此非常弱。

2 个答案:

答案 0 :(得分:2)

您不需要使用动态编程;如果需要,你可以使用简单的算术。

案例数为2 ^ n,因为给定总和的每个数字都是开启或关闭的。

从1到n的每个数字恰好用于总和的一半,因此每个数字都是2 ^(n-1)次。 1 + 2 + ... + n =(n - 1)* n / 2。

因此总和为(n-1)* n / 2 * 2 ^(n-1)。 对于n = 3,它是(4 * 3/2)* 4 = 24。

编辑:如果你真的想使用动态编程,这是一种方法。 动态编程利用保存子问题的结果来更快地解决超级问题。在这个问题中,子问题将是1 ... n-1的所有组合的总和。

所以从n - &gt;创建一个映射。 (组合数量,组合总数)。

初始化为1 - &gt; (2,1)。因为有两个组合{0,1}并且总和是1.包括0只会使数学更容易。

然后你的迭代步骤是使用映射。

让我们说(n-1) - &gt; (k,s),意思是有k个集合,其总和为1 ... n-1。

然后n的集合数是k * 2(每个组合要么具有n,要么没有)。 并且所有组合的总和是s +(s + k * n),因为你有前一个和(其中n缺失)加上所有n组合的总和(应该是k * n大于s因为那里是k个新组合,每个组合都有n。)

所以添加n - &gt; (2 * k,2 * s + k * n)。

你的最终答案是n - &gt; (K,S)。

答案 1 :(得分:2)

让dp [n]成为结果,因此:

dp[1] = 1
dp[n] = 2 * dp[n-1] + 2^(n-1) * n

首先,很明显dp [1] = 1

第二,dp [n]是包含n和sum的总和,它不包含n

EG:dp [3] = {(1)(2)(1,2)} + {(3),(1,3),(2,3),(1,2,3)} < / p>

我们可以发现dp [n-1]出现两次,n的数量出现2 ^(n-1)次

我想也许这就是你想要的。