子集和的总方式的递归关系

时间:2015-07-20 20:06:53

标签: algorithm recursion recurrence subset-sum

我试图找出在子集求和问题中达到目标的总方式。以下是我的方法。

如果' j'的总和,则让DP [i,j]为1元素总结为' i'否则它是0,其中' a'是输入。所以,

DP[i, j] = DP[i, j-1] + DP[i - a[j], j-1]

输入[10,13,15,18,20,15]和目标= 30 ;我们正在寻找DP [30,6]作为答案。

我能够使用递归(http://ideone.com/0sHhDL),但我需要使用DP。

1 个答案:

答案 0 :(得分:0)

一旦编写了递归函数,我们需要添加以使其高效的是缓存返回值。修改是:在进行递归调用之前,检查那些参数的计算是否尚未完成。

int NMAX = 100;
int cache[NMAX][NMAX];
int answer;
// Returns true if there is a subset of set[] with sun equal to given sum
int isSubsetSum(int set[], int n, int sum)
{

    // Base Cases
    if (sum == 0) {
        answer++;
        return 0; //return false here as we are after all the sums
    }
    if (n == 0 && sum != 0)
        return 0;

    if(cache[n][sum] == -1) {

        // If last element is greater than sum, then ignore it
        if (set[n-1] > sum)
            return isSubsetSum(set, n-1, sum);

        /* else, check if sum can be obtained by any of the following
           (a) including the last element
           (b) excluding the last element   */
        cache[n][sum] = isSubsetSum(set, n-1, sum) || isSubsetSum(set, n-1, sum-set[n-1]);
    }
    return cache[n][sum];
}

// Driver program to test above function
int main()
{
    int set[] = {3, 34, 4, 12, 5, 2};
    int sum = 9;
    int n = sizeof(set)/sizeof(set[0]);
    for(int i=0; i<NMAX; i++) for(int j=0; j<NMAX; j++)
        cache[i][j] = -1;
    isSubsetSum(set, n, sum);
    printf("total %d\n", answer);
    return 0;
}

在代码中,行

cache[n][sum] = isSubsetSum(set, n-1, sum) || isSubsetSum(set, n-1, sum-set[n-1]);

等同于递归公式

DP[i, j] = DP[i, j-1] + DP[i - a[j], j-1]

不同之处在于,一个是上下,另一个是底部。