优化这种组合算法

时间:2014-07-29 01:44:10

标签: algorithm optimization combinatorics

假设您有一个 N 号码,这是您的目标号码。然后给你一系列 p 数字,你必须找到大于N的那些数字的最小总和,也就是说,它超出它的极小(或它等于它)。

您可以使用任何元素组合中的任何总和。 p 可以与 100 一样大。

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

如您所知,这些向量可以解释为 p 数字的每种可能的不同组合,其中第i个位置的 0 表示i-该数字不包含在组合中,而 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的倍数

问题:我一直在考虑优化算法的方法,我发现这是你可以做的最蛮力的事情,但是,我在这个目标上失败了。任何人都可以帮助我优化这个,所以最终的计算是合理的吗?这有一个时间限制,即使我忽略了,我确信它不会很高。

提前致谢。

1 个答案:

答案 0 :(得分:4)

目前,这对于p的所有必需值都不起作用。除了超时之外,int不会保持100位。有一个O(p)动态编程算法可以解决这个问题,如另一个问题所述:Linear algorithm to find minimum subset sum over a threshold