递归解决方案的动态规划解决方案

Posted

技术标签:

【中文标题】递归解决方案的动态规划解决方案【英文标题】:Dynamic Programming solution for a Recursion solution 【发布时间】:2014-09-21 19:40:26 【问题描述】:

给定一个输入 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 来完成此操作,因为我对此很不擅长。

【问题讨论】:

或者你可以只分析计算它:n*(n+1)*2**(n-2)。没有循环,没有递归,没有动态编程。很高兴发布推导的答案。 【参考方案1】:

您不需要使用动态规划;如果你愿意,你可以使用简单的算术。

案例的数量是 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 ->(组合数,组合总和)创建一个映射。

用 1 -> (2,1) 初始化。因为 0,1 有两种组合,总和为 1。包含 0 只会使数学更容易一些。

那么你的迭代步骤就是使用映射。

假设 (n-1) -> (k,s),这意味着有 k 个集合,对于 1 ... n-1,总和为 s。

那么n的集合数是k * 2(每个组合要么有n,要么没有)。 所有组合的总和是 s + (s + k * n),因为你有前一个总和(其中 n 缺失)加上所有组合的总和与 n(应该是 k * n 比 s 多,因为有是 k 个新组合,每个都有 n 个)。

所以添加 n -> (2*k,2*s + k*n)。

而你的最终答案是 n -> (k,s) 中的 s。

【讨论】:

您好,感谢您的回答。我知道​​这个解决方案,但我只是在寻找使用 Dynamic Programming 的解决方案。【参考方案2】:

设 dp[n] 为结果,因此:

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

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

其次,dp[n]是包含n和不包含n的和

E.G: dp[3] = (1) (2) (1,2) + (3), (1,3), (2,3), (1,2,3)

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

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

【讨论】:

以上是关于递归解决方案的动态规划解决方案的主要内容,如果未能解决你的问题,请参考以下文章

js 高级算法 - 动态规划

算法动态规划问题的常见解决办法

数据结构与算法 —— 动态规划

动态规划算法的套路,动态规划入门

09动态规划解决斐波那契数列

动态规划 - 分词