记忆递归算法

时间:2017-11-07 04:47:10

标签: c algorithm recursion dynamic-programming memoization

问题:给定金额m和数字数组b[]打印"Yes"如果m可以通过添加数组中的任意数量的元素而不重复来形成它们。

这就是我想出来的;如何在其中添加记忆矩阵?

#include<stdio.h>

int check(int b[],int n,int m){ 
    if(m==0){
        return 1;
    }
    if(m<0){
        return 0;
    }
    if(n<=0 && m>0){
        return 0;
    }
    return check(b,n-1,m-b[n-1]) + check(b,n-1,m);
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d",&n);
        scanf("%d",&m);
        int b[n];
        for(int i=0;i<n;i++){
            scanf("%d",&b[i]);
        }
        if(check(b,n,m)>0){
            printf("Yes\n");
        }else{
            printf("No\n");
        }

    }    
    return 0;
}

任何人都可以帮我把记忆矩阵加入其中吗?

1 个答案:

答案 0 :(得分:4)

memoization缓存的关键字包括n的第一个b元素,加上m。从这些表单中形成一个字符串,并将其用作哈希表的键。

......但重点是什么?在每次递归中n递减时,只有两种情况,其中memoization将有所帮助:

  • 如果对完全相同的号码列表进行了非递归通话check,并且在m之前调用了check

  • m-b[n-1] == m时,也就是说b[n-1] == 0时。

第一种情况不太可能(并且随着列表的大小增加而减少,这是备忘录最有帮助的时候),第二种情况很容易避免。只需替换

return check(b,n-1,m-b[n-1]) + check(b,n-1,m);

return b[n-1] == 0
   ? check(b,n-1,m) * 2
   : check(b,n-1,m) + check(b,n-1,m-b[n-1]);