C/C++类似于子集和的算法的实现

发布于 2024-08-19 14:42:08 字数 348 浏览 5 评论 0原文

这个问题比背包(或其一种类型,没有值,只有正权重)更简单。该问题包括检查一个数字是否可以是其他数字的组合。该函数应返回 truefalse

例如,

112 和具有 { 17, 100, 101 } 的列表应返回 false,具有相同列表的 469 应返回 true35 应返回 false119 应返回 true 等...

编辑:子集和问题比背包问题更准确。

The problem is simpler than knapsack (or a type of it, without values and only positive weights). The problem consists of checking whether a number can be a combination of others. The function should return true or false.

For example,

112 and a list with { 17, 100, 101 } should return false, 469 with the same list should return true, 35 should return false, 119 should return true, etc...

Edit: subset sum problem would be more accurate for this than knapsack.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

雪若未夕 2024-08-26 14:42:08

这是子集和问题的一种特殊情况,其中的集合仅包含一个负数(即,将 112 和 { 17, 100, 101 } 表示为 { -112, 17, 100, 101 })。维基百科页面上有一些算法,http://en.wikipedia.org/wiki/Subset_sum_problem。

This is a special case of the Subset Sum problem, with sets that only contain one negative number (i.e., express 112 and { 17, 100, 101 } as { -112, 17, 100, 101 }). There's a few algorithms on the Wikipedia page, http://en.wikipedia.org/wiki/Subset_sum_problem.

不再让梦枯萎 2024-08-26 14:42:08

对您有帮助的观察是,如果您的列表是 {a, b, c...} 并且您要测试的数字是 x,则仅当 x 或 xa 可以时,x 才能写为子列表的和写为子列表 {b, c, ...} 的和。这使您可以编写一个非常简单的递归算法来解决问题。

编辑:这是一些代码,考虑到下面的评论。未经测试,因此可能有错误;并且不一定是最快的。但对于小型数据集,它可以很好地完成工作。

bool is_subset_sum(int x, std::list::const_iterator start, std::list::const_iterator end)
{
  // for a 1-element list {a} we just need to test a|x
  if (start == end) return (x % *start == 0); 

  // if x is small enough  we don't need to bother testing x - a
  if (x<a) return is_subset_sum (x, start+1, end);

  // the default case. Note that the shortcut properties of || means the process ends as soon as we get a positive.
  return (is_subset_sum (x, start+1, end) || is_subset_sum (x-a, start, end));
}

An observation that will help you is that if your list is {a, b, c...} and the number you want to test is x, then x can be written as a sum of a sublist only if either x or x-a can be written as a sum of the sublist {b, c, ...}. This lets you write a very simple recursive algorithm to solve the problem.

edit: here is some code, taking into account the comments below. Not tested so probably buggy; and not necessarily the fastest. But for a small dataset it will get the job done neatly.

bool is_subset_sum(int x, std::list::const_iterator start, std::list::const_iterator end)
{
  // for a 1-element list {a} we just need to test a|x
  if (start == end) return (x % *start == 0); 

  // if x is small enough  we don't need to bother testing x - a
  if (x<a) return is_subset_sum (x, start+1, end);

  // the default case. Note that the shortcut properties of || means the process ends as soon as we get a positive.
  return (is_subset_sum (x, start+1, end) || is_subset_sum (x-a, start, end));
}
萌酱 2024-08-26 14:42:08

请注意,随着查询数量变大,正结果会变得更密集。例如,所有大于 100^2 的数字都可以通过 { 17, 100, 101 } 生成。因此,最佳算法可能取决于查询的数量是否远大于集合的成员。您可能会研究一下场论。

至少,您知道如果该集合的最大公约数不在查询中,则结果始终为假,并且可以在可忽略不计的时间内进行检查。

Note that positive results become denser as the queried number becomes larger. For example, all numbers greater than 100^2 can be generated by { 17, 100, 101 }. So the optimal algorithm may depend upon whether the queried number is much greater than the set's members. You might look into field theory.

At the least, you know the result is always false if the greatest common divisor of the set is not in the query, and that can be checked in negligible time.

离鸿 2024-08-26 14:42:08

如果要到达的数字不太大,您可能可以从集合中生成落在 [1,N] 范围内的所有可到达数字。

问题:使用列表 L 中的元素达到 N,其中 N 足够小,不必担心大小为 N 的向量 元素的大小。

算法:

  • 生成大小为 N 的向量 V
  • 为列表 L 中的每个元素 l
    • 对于 V 中的每个可达元素 v
      • 将 V 中的所有元素 v + n*l 标记为可达

If the number to reach is not too large, you can probably generate all the reachable numbers from the set that fall in the range [1,N].

Problem: Reach N using the elements in the list L, where N is small enough not to worry about a vector of size N elements' size.

Algorithm:

  • Generate a vector V of size N
  • For each element l in the list L
    • For each reachable element v in V
      • mark all elements v + n*l in V as reachable
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文