【问题标题】:Number of unique combination of numbers from an array whose sum equals to target (Recursion + Memoization)数组中数字的唯一组合数,其总和等于目标(递归 + 记忆)
【发布时间】:2020-11-18 12:59:50
【问题描述】:

动态编程题:

考虑一个玩家可以在一个游戏中获得 3 或 5 或 10 分的游戏 移动。

给定总分 n,找出达到给定分数的不同组合的数量。

我正在尝试使用递归+记忆来解决它。

我的仅递归方法:

long long int countrecur(long long int n, long long int min)
{   
    if (n==0)
        return 1;     
    
    else if(n<0)
        return 0;
    
    else 
    {
        long long int ans=0;

        if(min<=3)
            ans+=countrecur(n-3,3);

        if(min<=5)
            ans+=countrecur(n-5,5);

        if(min<=10)
            ans+=countrecur(n-10,10);
        
        return ans;
    }

}

long long int count(long long int n)
{
   return countrecur(n,0);
}

它似乎有效,但我无法找到如何记住子问题的结果。

递归+记忆尝试:

#include<iostream>
#include<vector>
using namespace std;

long long int countrecur(long long int n, long long int min, vector<long long int> &dp)
{
    if (n < 3 && n!=0)
        return 0;
    
    if (n == 0||dp[n]!=0)
        return dp[n];

    else
    {
        long long int ans = 0;
        if (min <= 3)
            ans += countrecur(n - 3, 3,dp);
        
        if (min <= 5)
            ans += countrecur(n - 5, 5,dp);
        
        if (min <= 10)
            ans += countrecur(n - 10, 10,dp);

        dp[n] = ans;

        return ans;
    }

}

long long int count(long long int n, vector<long long int>& dp)
{
    return countrecur(n, 0,dp);
}

int main()
{
    int n;
    cin >> n;
    vector<long long int>dp(n+1, 0);
    dp[0] = 1;
    cout << count(n,dp) << endl;
}

对于像 n=20 这样的输入似乎失败了,其中一些分支在递归树的根部变得相等。

20=15+5; 20={10,5}+{5}={10,5,5}

20=10+10; 20={5,5}+{10}={5,5,10}

【问题讨论】:

    标签: algorithm recursion dynamic-programming


    【解决方案1】:

    假设你想要一个8分的路,

    所以只有一种方法可以进行更改,即:

    {3,5}

    但是,上面的代码为它返回 2,因为:

    这是对 (3,5) 和 (5,3) 的不同考虑。


    那么,该怎么办?

    递归应该遵循给定的持续值,或者根本不再次使用它。

    这意味着应该保持值的使用顺序


    伪代码:

    Array = [3,5,10]
    index = 0 
    value = 20
    
    ways = Recursion(Array,index,value)
    

    递归:

    function Recursion(Array,index,value)
    
        if(value == 0)
            return 1
    
        if(value < 0)
            return 0
    
        if(index == 3)
            return 0
    
        return Recursion(Array,index,value - Array[index]) + Recursion(Array,index+1,value)
    

    记忆:

    为了记忆解法,我们需要使用两个参数,即值和索引。


    为什么问题中的代码没有返回正确的输出?

    因为对于每一个索引,我们都会有不同的方式来达到相同的值。

    举个例子:

    value = 15
    dp = [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] // dp array
    

    min == '3' 的方法是一种:

    dp = [1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1]
    

    在经历 min == '5' 时:

    dp = [1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1]
    

    但是当递归进行 min == '10' 和 n == 5 时:

    1 is returned but there is no way for the score of 10 to make a total of 5.
    

    这就是为什么上面记忆的代码将返回 4 对应 15,但正确的输出应该是 3。

    【讨论】:

    • 我相信我的递归+记忆方法输出 1 表示输入 = 8。我尝试使用这些条件子句来保持顺序。
    • @Shubhashish 现在我认为我的回答可以解决您的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-26
    • 1970-01-01
    • 2021-01-25
    • 2012-03-11
    • 1970-01-01
    • 2023-01-31
    • 2012-11-26
    相关资源
    最近更新 更多