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

Dynamic Programming solution for a Recursion solution

本文关键字:解决方案 编程 动态 递归      更新时间:2023-10-16

给定一个输入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';
    }
}

编辑尽管这个问题可以用这个级数在恒定时间内解决。

但我想知道如何使用Dynamic Programming来实现这一点,因为我在这方面非常薄弱。

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

案例数为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。

EDIT:如果您真的想使用动态编程,这里有一种方法。动态规划利用保存子问题的结果来加快超级问题的求解速度。在这个问题中,子问题是从1。。。n-1.

因此,从n->(组合的数量,组合的总和)创建一个映射。

使用1->(2,1)初始化。因为有两个组合{0,1},并且和为1。包括0只会让数学运算变得简单一点。

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

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

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

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

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

设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)

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

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