我正在寻找关于动态编程问题的一些指示。我找不到任何有关如何解决此类问题的相关信息。我知道如何使用动态编程解决的唯一问题是当我有两个序列并创建这些序列的矩阵时。但我不知道如何将其应用于以下问题...
如果我有一个集合A = {7,11,33,71,111}和一个数字B.那么作为A的子集的C,包含来自A的元素,它构建了和B.
实施例
A = {7,11,33,71,111}
If B = 18, then C = {7,11} (because 7+11 = 18)
If B = 3, then there is no solution
感谢这里的任何帮助,我只是不知道在解决这些问题时如何思考。我也找不到任何一般方法,只有基因序列的一些例子和类似的东西。
答案 0 :(得分:5)
动态规划是一个广泛的解决方案类别,其中部分解决方案保留在某个结构中,以便下一次迭代构建,而不是一遍又一遍地重新计算中间结果。
如果我对这个特定问题采取动态方法,我可能会保留一个运行列表,其中包含上一步中可计算的每个总和,以及用于计算该总和的集合。
因此,例如第一次迭代我的工作集将包含{null, 7}
,然后我会将11
添加到该集合中的所有内容以及集合本身(让我们假装null+11=11
目前)。现在我的工作集将包含{null, 7, 11, 18}
。对于集合中的每个值,我会跟踪我得到的结果:7
映射到原始集{7}
,18
映射到原始集{7,11}
。当A)生成目标值或B)原始集合耗尽而没有找到值时,迭代将结束。你可以用一个有序集来优化负面情况,但是我会把这一点告诉你。
解决此问题的方法不止一种。这是一个动态解决方案,因为它需要构建一组2^(size of set)
成员,所以效率不高。但是一般方法对应于创建动态编程来解决的问题。
答案 1 :(得分:0)
I think dynamic approach depend on B and number elements of A.
在这种情况下,我提出了一种动态方法,其中B *数字元素为A <= 1.000.000
Use call F[i,j] is true if use can use from A[1] to A[j] to build i and false otherwise
所以你必须选择每一步:
使用[j]然后F [i,j] = F [i-a [j],j-1]
不要用户[j]然后用F [i,j] = F [i,j-1]
然后,如果现有F [B,*] = 1,则可以构建B。
Bellow是示例代码:
#include<stdio.h>
#include<iostream>
using namespace std;
int f[1000][1000], a[1000], B,n;
// f[i][j] = 1 => can build i when using A[1]..a[j], 0 otherwisw
int tmax(int a, int b){
if (a>b) return a;
return b;
}
void DP(){
f[0][0] = 1;
for (int i=1;i<=B;i++)
for (int j=1;j<=n;j++)
{
f[i][j] = f[i][j-1];
if (a[j]<=i)
f[i][j] = tmax(f[i-a[j]][j-1], f[i][j]);
}
}
int main(){
cin >> n >> B;
for (int i=1;i<=n;i++) cin >>a[i];
DP();
bool ok = false;
for (int i=1;i<=n;i++){
if (f[B][i]==1) {
cout<<"YES";
ok = true;
break;
}
}
if (!ok) cout <<"NO";
}