算法 - 动态编程 - 两个数组的子集和

时间:2015-12-14 06:30:42

标签: algorithm subset subset-sum

我的作业包括动态编程问题:

  

给出两个自然整数数组(a1,a2,...,an和b1,b2,...,bn)   所有这些都小于n ^ 2,并且还给出了数字B.   小于n ^ 3。

     

你需要阻止是否有一个数组(c1,c2,...,cn):

     

enter image description here

     

对于每个1< = i< = n,ci = ai或ci = bi。

     

*此算法必须使用动态编程编写。

     

*另外,我们需要改变什么来实际获得给出Sum(c)= B

的数组c

另一种看问题的方法是说c等于a的子集,而b的补充子集等于。

这是我为解决这个问题而编写的递归伪代码:

W(a,b,i, N)
    if i==-1
        if N==0     return true;
        else        return false;
    return W(a,b,i-1,N-a[i]) || W(a,b,i-1,N-b[i]);

T(n) = 2^n

在这里,要返回最佳路径,只需将其存储在树中,然后从(好)端转到开头

如何使用动态编程来编写?这甚至可以帮助运行时间吗?因为递归解决方案具有独立的结果。

*我搜索谷歌这个问题,但发现了“子集总和问题”,这是不同的。

1 个答案:

答案 0 :(得分:1)

感谢@PhamTrung,我有一个解决方案:

让矩阵[B,n](最大尺寸[n ^ 3,n])

示例:(n = 3,B = 8)

    0   1       2       3       4       ... 8
0   T   F       F       F       F       ... F
1   F   (1,1)   (1,2)   (1,3)   (1,4)   ... (1,8)
2   F   F       (2,2)   (2,3)   (2,4)   ... (2,8)
3   F   F       F       (3,3)   (3,4)   ... (3,8)

伪代码:

//Generate the matrix
A = new Array(n+1,B+1)
for(i: 0 to n) //run over lines
    for(j: 0 to B) //run over B columns
        if i==0 //if we are in the first row
            A[i,j] = j==0; //if this is [0,0], it is true. else, false
        else if i>j //if we have more numbers than the sum
            A[i,j] = false; //it cannot happen
        else
            //general case:
            //if we remove a[i] or b[i], will we get to a true statement?
            A[i,j] = (j-a[i] >= 0 && A[i-1, j-a[i]]) || (j-b[i] >= 0 && A[i-1, j-b[i]]);

is_set(n,B,A)
    if(A[n,B])
        return true;
    return false;

公式:

[0,j],j!=0 = F
[0,0]   = T
i > j   = F
i <= j  = (i-1, j - a[i]) || (i-1, j - b[i])

获取路线:

要获得构建C的路径,我们还将保存每个真实点0(= a)或1(= b),并从底部到顶部。