动态规划问题

发布于 2024-08-05 22:57:49 字数 376 浏览 2 评论 0原文

我正在寻找有关动态规划问题的一些指导。我找不到任何有关如何解决此类问题的相关信息。我知道如何使用动态规划解决的唯一问题是当我有两个序列并创建这些序列的矩阵时。但我不知道如何将其应用于以下问题...

如果我有一个集合 A = {7,11,33,71,111} 和一个数字 B。那么 C 是 A 的子集,包含示例

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

感谢这里的任何帮助,我只是不知道在解决此类问题时如何思考。我也找不到任何通用方法,只有一些关于基因序列之类的例子。

I'm looking for some pointers about a dynamic programming problem. I cannot find any relevant information about how to solve this kind of problem. The only kind of problem I know how to solve using dynamic programming is when I have two sequences and create a matrix of those sequences. But I don't see how I can apply that to the following problem...

If I have a set A = {7,11,33,71,111} and a number B. Then C which is a subset of A, contains the elements from A which builds the sum B.

EXAMPLE:

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

Thankful for any help here, I just don't know how to think when solving these kind of problems. I cannot find any general method either, only some examples on gene sequences and stuff like that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

过期以后 2024-08-12 22:57:49

动态编程是一类广泛的解决方案,其中部分解决方案保留在某种结构中,供下一次迭代构建,而不是一遍又一遍地重新计算中间结果。

如果我要对这个特定问题采取动态方法,我可能会保留上一步中可计算的每个总和的运行列表,以及用于计算该总和的集合。

因此,例如,我的工作集的第一次迭代将包含 {null, 7},然后我会将 11 添加到该集中的所有内容以及该集本身(让我们现在假设 null+11=11)。现在我的工作集将包含 {null, 7, 11, 18}。对于集合中的每个值,我将跟踪如何获得该结果:因此 7 映射到原始集合 {7}18 > 映射到原始集合{7,11}。当 A) 生成目标值或 B) 原始集合耗尽但未找到该值时,迭代将结束。您可以使用有序集来优化负面情况,但我会将其留给您来解决。

解决这个问题的方法不止一种。这是一个动态解决方案,效率不是很高,因为它需要构建一组 2^(size of set) 成员。但一般方法与动态规划的创建目的相对应。

Dynamic programming is a broad category of solutions wherein a partial solution is kept in some structure for the next iteration to build upon instead of having it recalculate the intermediate results over and over again.

If I were to take a dynamic approach to this particular problem, I would probably keep a running list of every sum calculable from the previous step, as well as the set used to compute that sum.

So for example the first iteration my working set would contain {null, 7}, then I would add 11 to everything in that that set as well as the set itself (let's pretend that null+11=11 for now). Now my working set would contain {null, 7, 11, 18}. For each value in the set, I would keep track of how I got that result: so 7 maps to the original set {7} and 18 maps to the original set {7,11}. Iteration would end when either A) the target value is generated or B) the original set is exhausted without finding the value. You could optimize the negative case with an ordered set, but I'll leave figuring that out to you.

There is more than one way to approach this problem. This is a dynamic solution, and it's not very efficient as it needs to build a set of 2^(size of set) members. But the general approach corresponds to what dynamic programming was created to solve.

一梦等七年七年为一梦 2024-08-12 22:57:49
I think dynamic approach depend on B and number elements of A.

在这种情况下,我建议采用动态方法,其中 A <= 1.000.000 的 B*number 元素

Use call F[i,j] is true if use can use from A[1] to A[j] to build i and false otherwise

因此,您必须选择每一步:

使用 a[j] 然后 F[i,j]=F[ia[j],j -1]

不要使用 a[j] 然后 F[i,j] = F[i,j-1]

然后如果存在 F[B,*]=1 ,则可以构建 B。

下面是示例代码:

#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";
}
I think dynamic approach depend on B and number elements of A.

I suggested a dynamic approach in this case with B*number element of 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

So each step you have to choise:

use a[j] then F[i,j]=F[i-a[j],j-1]

don't user a[j] then F[i,j] = F[i,j-1]

Then if existing a F[B,*]=1 ,you can build B.

Bellow is example code:

#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";
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文