【问题标题】:Optimizing this combinatorics algorithm优化这个组合算法
【发布时间】:2014-07-29 10:08:40
【问题描述】:

假设给你一个数字,N,这是你的目标数字。然后给你一系列 p 数字,你必须找到这些数字中大于 N 的最小总和,即最小地超过它(或等于它)。

您可以取任意元素的任意组合的总和。 p 可以大到 100

我当前的算法:扫描所有信息后,我创建了一个 100 位长的位集,并使用循环将所有整数从 0 转换为 ( 2^p)-1 ,有效地以 000...000111...111 之间的所有二进制数结束。

如您所知,这些向量可以解释为 p 数字的每个可能的不同组合,其中第 i 个位置的 0 表示第 i- th 数字不包含在组合中,而 1 表示包含。

现在,通过遍历这个 bitset 并检查每个组合,我肯定能够达到我的目标,因为我会检查每个可能的组合。如果所有数字加在一起还不足以达到目标,那么就没有解决方案。

实际代码:

#include <cstdlib>
#include <iostream>
#include <cmath>
#include <bitset>

using namespace std;

int main()
{
    int N, p;
    cin >> N >> p;
    int bars[p], tot = 0;
    for (int j=0;j<p;j++){
        cin >> bars[j];
        tot += bars[j];
    }
    if (tot < N) cout << "NO SOLUTION" << endl;
    else {
         int diff = 3000;
         for (int j=0;j<pow(2.0,p)-1;j++){
             tot = 0;
             bitset<100> x(j);
             for (int k=0;k<p;k++){
                 if (x[k] == 1) tot += bars[k];
             }
             if (tot == N) {
                cout << N << endl;
                break;
             }
             if (tot-N>0&&tot-N<diff) diff = tot-N;
         }
         cout << N+diff << endl;
    }
    return 0;
}

问题:由于我们最多可以有 100 个数字,因此可能的组合数量巨大,而且它只是不可行。我已经能够通过使用这种方法解决此类问题,但它们最多包含 20 个数字,这使得计算成为可能。这让我想到一定有更好的方法来计算问题。

我没有使用的额外信息:问题来自我在设计算法时没有考虑的额外信息,这些信息可能对优化算法有用。这些数据是:

  • 100≤N≤2500
  • N 是 10 的倍数
  • 5≤p≤100
  • 每个数字都在 50 到 2500 之间
  • 它们也是 10 的倍数

问题:我一直在考虑优化我的算法的方法,我意识到这是你能做的最暴力的事情,但是,我在这个目标上失败了。任何人都可以帮我优化这个,所以结果计算是合理的吗?这个是有时间限制的,虽然我忽略了,但我敢肯定它不会太高。

提前致谢。

【问题讨论】:

  • 目前除了“尝试所有组合”之外,您并没有真正的算法,从技术上讲,您可以称其为算法,但它确实从琐碎的“尝试所有组合”中没有取得任何进展。你还尝试过什么?到目前为止,对我来说,您似乎还没有尝试足够的方法。
  • 这看起来很像integer knapsack problem
  • 感谢@Gassa 的参考,确实非常相似,我一定会检查一下,看看我能用这些新信息做什么;)
  • 谷歌的反向背包问题。

标签: algorithm optimization combinatorics


【解决方案1】:

目前这不适用于 p 的所有必需值。除了超时之外,int 不会保存 100 位。有一个 O(p) 动态规划算法可以解决这个问题,正如另一个问题中提到的:Linear algorithm to find minimum subset sum over a threshold

【讨论】:

  • 谢谢,这正是我正在寻找的算法。你和 Gassa 真的帮助我解决了类似背包的问题,​​对此我非常感激 ;)
猜你喜欢
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 2021-01-20
  • 1970-01-01
  • 2021-02-25
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
相关资源
最近更新 更多