假设您有一个 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个数字,这使得计算成为可能。这让我想到必须有一个更好的方法来计算问题。
我没有使用过的额外信息:问题来自我在设计算法时未考虑的额外信息,这可能对优化算法有用。这些基准是:
问题:我一直在考虑优化算法的方法,我发现这是你可以做的最蛮力的事情,但是,我在这个目标上失败了。任何人都可以帮助我优化这个,所以最终的计算是合理的吗?这有一个时间限制,即使我忽略了,我确信它不会很高。
提前致谢。
答案 0 :(得分:4)
目前,这对于p的所有必需值都不起作用。除了超时之外,int不会保持100位。有一个O(p)动态编程算法可以解决这个问题,如另一个问题所述:Linear algorithm to find minimum subset sum over a threshold