递归解决方案的动态规划解决方案
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)次
我想也许这就是你想要的。
【讨论】:
以上是关于递归解决方案的动态规划解决方案的主要内容,如果未能解决你的问题,请参考以下文章