【问题标题】:Number of subsequences of size k and sum s大小为 k 且总和为 s 的子序列数
【发布时间】:2019-09-09 12:18:46
【问题描述】:

考虑一个长度为 n 的数组 A。令 k 为要生成的子序列的长度。我想要做的是获得长度为 k 和 sum 的子序列的数量。

例子:

A = [1,1,2,2,3]
s = 4
k = 2

所以输出将是 3 -> [{1,3}, {1,3}, {2,2}]。

注意: 1 被视为单独处理的两倍。 长度为 k 的子序列总数为 Cₖ(此处为 10)。

我尝试了什么:我尝试使用 Pascals Identity 生成所有长度为 k 的子序列,分别计算它们的总和并检查它是否等于 sum s。我怎样才能使算法更有效?

谁能帮我解决这个问题?

【问题讨论】:

  • “有人可以帮我解决这个问题吗?” 表示您已经尝试过了,您能否向我们展示您的代码,然后我们可以帮助确定具体问题
  • 这是一个经典的计算机科学问题/问题。你已经做了哪些研究?查找 NP-Hard 问题。请阅读How to Askminimal reproducible example
  • 您的代码有效吗? 那么也许您应该改为在Code Review SE 上发帖?
  • 如您所知,这可以使用动态编程来解决(嗯,很可能在您的情况下)。简而言之,您必须执行以下操作:1)确定一个计算结果的递归函数。 2)添加记忆(通常,以减少从指数到多项式的复杂性)。第一部分可能很棘手。如果你想不出一个,你应该向你的导师(或任何告诉你使用动态编程的人)寻求帮助。通常的想法是逐个处理项目并维护某种部分解决方案。

标签: c++ dynamic-programming subsequence


【解决方案1】:

我对 C++ 了解不多,但这似乎可行:

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

double f(int A[], int n, int s, int k, int i, map<array<int, 3>, double> memo){
  if (k == 0)
    return s == 0 ? 1 : 0;
  if (i == n || s < 0 || k < 0)
    return 0;
  return memo[array<int, 3>{s, k, i}] =
    f(A, n, s - A[i], k - 1, i + 1, memo) + f(A, n, s, k, i + 1, memo);
}

int main(){
   map<array<int, 3>, double> memo;
   int A[5] = {1, 1, 2, 2, 3};
   double result = f(A, 5, 4, 2, 0, memo);
   cout << result;
}

【讨论】:

    【解决方案2】:

    这可以使用背包法解决。对于每个元素,您可以包含它或排除它。这是cpp代码:

    ll knap(int values[],int n, int i, int length, int sum) { //ll is long long
        if(s<0 || i>n-1 ||l<0) return 0;
        if(s==0 && l==0) return 1;
        ll a = knap(values,n,i+1,l-1,s-values[i]); //including current element
        ll b = knap(values,n,i+1,l,s);  //not including the current element and moving on
        return (a+b);
    }
    

    【讨论】:

      猜你喜欢
      • 2021-02-16
      • 1970-01-01
      • 2013-08-06
      • 2020-06-26
      • 2022-01-05
      • 2020-05-12
      • 2015-07-12
      • 2015-08-14
      • 2016-06-13
      相关资源
      最近更新 更多