尽管如此,我试图在标题中总结一下这个问题,但我认为如果我开始讨论这个问题的实例会更好:
Primes列表= {2 3 5 7 11 13}
分解模式= {1 1 2 1}
对于上述输入,程序应生成以下数字列表:
到目前为止,我理解由于模式的长度是任意大的(就像素数列表一样),我需要使用递归函数来获得所有组合。我真正的,真正困难的是 - 如何制定函数的参数/何时调用等等。这是我迄今为止开发的:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
static const int factors[] = {2, 3, 5, 7, 11, 13};
vector<int> vFactors(factors, factors + sizeof(factors) / sizeof(factors[0]));
static const int powers[] = {1, 1, 2, 1};
vector<int> vPowers(powers, powers + sizeof(powers) / sizeof(powers[0]));
// currPIdx [in] Denotes the index of Power array from which to start generating numbers
// currFidx [in] Denotes the index of Factor array from which to start generating numbers
vector<int> getNumList(vector<int>& vPowers, vector<int>& vFactors, int currPIdx, int currFIdx)
{
vector<int> vResult;
if (currPIdx != vPowers.size() - 1)
{
for (int i = currPIdx + 1; i < vPowers.size(); ++i)
{
vector<int> vTempResult = getNumList(vPowers, vFactors, i, currFIdx + i);
vResult.insert(vResult.end(), vTempResult.begin(), vTempResult.end());
}
int multFactor = pow((float) vFactors[currFIdx], vPowers[currPIdx]);
for (int i = 0; i < vResult.size(); ++i)
vResult[i] *= multFactor;
}
else
{ // Terminating the recursive call
for (int i = currFIdx; i < vFactors.size(); ++i)
{
int element = pow((float) vFactors[i], vPowers[currPIdx]);
vResult.push_back(element);
}
}
return vResult;
}
int main()
{
vector<int> vNumList = getNumList(vPowers, vFactors, 0, 0);
cout << "List of numbers: " << endl;
for (int i = 0; i < vNumList.size(); ++i)
cout << vNumList[i] << endl;
}
当我运行上述内容时,我的列表不正确:
List of numbers:
66
78
650
14
22
26
我已经不知何故遇到了一个心理障碍,因为我似乎无法弄清楚如何适当地改变递归调用中的最后一个参数(我认为这是我的程序不工作的原因)!! < / p>
如果有人能够用缺少的逻辑调整我的代码(或者甚至指向我 - 我不是在寻找一个完整的解决方案!),那将是非常好的。如果你能限制你对标准C ++的回答,我将非常感激!
(如果有人注意到我错过了给定模式的排列,这会导致其他数字,如2.3.5.7 ^ 2等 - 不用担心,我打算在所有可能的排列上重复这个算法通过使用next_permutate获得给定模式!)。
PS:不是作业/面试问题,只是一个非常有趣的Project Euler问题的算法的一部分(我想你甚至可以猜出哪一个:))。
编辑:我已经自己解决了这个问题 - 我已将其作为答案发布。如果你喜欢它,那就投赞吧(我不能接受它作为答案,直到得到的票数超过其他答案!)...答案 0 :(得分:2)
暂时忘记分解。你要解决的问题是有两个列表P和F并找到P中p和f中f的所有可能配对(p,f)。这意味着你将拥有| P | * | P | -1 ... * | P | - (| F | -1)可能的配对(从P到F的第一个元素分配一个,留下| P | -1可能匹配第二个元素等)。您可能希望在代码中分离问题的这一部分。如果你以这种方式递归,最后一步是选择从P到F的最后一个元素的剩余元素。这有帮助吗?我必须承认,我不能很好地理解你的代码,以提供适合你当前状态的答案,但这就是我一般的方法。
答案 1 :(得分:1)
好吧,我自己想出了这个!这是它的代码(我希望这是不言自明的,但我可以澄清以防任何人需要更多细节):
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
static const int factors[] = {2, 3, 5, 7, 11, 13};
vector<int> vFactors(factors, factors + sizeof(factors) / sizeof(factors[0]));
static const int powers[] = {1, 1, 2, 1};
vector<int> vPowers(powers, powers + sizeof(powers) / sizeof(powers[0]));
// idx - The index from which the rest of the factors are to be considered.
// 0 <= idx < Factors.size() - Powers.size()
// lvl - The lvl of the depth-first tree
// 0 <= lvl < Powers.size()
// lvlProd - The product till the previous level for that index.
void generateNumList
(
vector<int>& vPowers,
vector<int>& vFactors,
vector<int>& vNumList,
int idx,
int lvl,
long lvlProd
)
{
// Terminating case
if (lvl == vPowers.size() - 1)
{
long prod = pow((float) vFactors[idx], vPowers[lvl]) * lvlProd;
vNumList.push_back(prod);
}
else
{
// Recursive case
long tempLvlProd = lvlProd * pow((float) vFactors[idx], vPowers[lvl]);
for (int i = idx + 1; i < vFactors.size(); ++i)
generateNumList(vPowers, vFactors, vNumList, i, lvl + 1,
tempLvlProd);
}
}
vector<int> getNumList(vector<int>& vPowers, vector<int>& vFactors)
{
vector<int> vNumList;
for (int i = 0; i < vFactors.size(); ++i)
generateNumList(vPowers, vFactors, vNumList, i, 0, 1);
return vNumList;
}
int main()
{
vector<int> vNumList = getNumList(vPowers, vFactors);
cout << endl << "List of numbers (" << vNumList.size() << ") : " << endl;
for (int i = 0; i < vNumList.size(); ++i)
cout << vNumList[i] << endl;
}
上面代码的输出(我必须工作很长时间才能在算法上摆脱重复的条目!):
List of numbers (15) :
1050
1650
1950
3234
3822
9438
5390
6370
15730
22022
8085
9555
23595
33033
55055
real 0m0.002s
user 0m0.001s
sys 0m0.001s