【发布时间】:2014-07-29 10:08:40
【问题描述】:
假设给你一个数字,N,这是你的目标数字。然后给你一系列 p 数字,你必须找到这些数字中大于 N 的最小总和,即最小地超过它(或等于它)。
您可以取任意元素的任意组合的总和。 p 可以大到 100。
我当前的算法:扫描所有信息后,我创建了一个 100 位长的位集,并使用循环将所有整数从 0 转换为 ( 2^p)-1 ,有效地以 000...000 和 111...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