假设我有一个目标数和一个可能的值列表,我可以从中选择创建一个序列,一旦选定每个数字后将它们相加,总和会等于目标:
target = 31
list = 2, 3, 4
possible sequence: 3 2 4 2 2 2 4 2 3 2 3 2
我希望:
- 首先确定是否有能够到达目标的序列。
- 返回其中一个(可能的)序列。
这是我的尝试:
#include <iostream>
#include <random>
#include <chrono>
#include <vector>
inline int GetRandomInt(int min = 0, int max = 1) {
uint64_t timeSeed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
std::seed_seq ss{ uint32_t(timeSeed & 0xffffffff), uint32_t(timeSeed >> 32) };
std::mt19937_64 rng;
rng.seed(ss);
std::uniform_int_distribution<int> unif(min, max);
return unif(rng);
}
void CreateSequence(int target, std::vector<int> &availableNumbers) {
int numAttempts = 1;
int count = 0;
std::vector<int> elements;
while (count != target) {
while (count < target) {
int elem = availableNumbers[GetRandomInt(0, availableNumbers.size() - 1)];
count += elem;
elements.push_back(elem);
}
if (count != target) {
numAttempts++;
count = 0;
elements.clear();
}
}
int size = elements.size();
std::cout << "count: " << count << " | " << "num elements: " << size << " | " << "num attempts: " << numAttempts << std::endl;
for (auto it = elements.begin(); it != elements.end(); it++) {
std::cout << *it << " ";
}
}
int main() {
std::vector<int> availableNumbers = { 2, 3, 4 };
CreateSequence(31, availableNumbers);
}
但是,如果数字列表不能恰当地达到这样的总和,则它可能无限循环; 例如:
std::vector<int> availableNumbers = { 3 };
CreateSequence(8, availableNumbers);
不存在任何连续三个数的和为8。此外,如果列表很大且目标数字很高,则可能会导致大量的处理(因为许多while检查失败)。
您将如何实现这种算法?
回溯
范式可能会有用:如果当前总和超过了目标,你可以放弃该分支并移动到另一个排列。 - ihavenoidea