下面的函数生成段之间的空间排列,返回false时,它不能产生任何更多:
template <typename SpaceIter>
bool next(SpaceIter start, SpaceIter finish)
{
for (SpaceIter i = start; i != finish; ++i)
{
// Find the first non-minimised space.
if (*i)
{
SpaceIter j = i; ++j;
if (j == finish)
return false;
int s = *i; // Remember *i, in case i == start.
// Preserve the invariant: Σ(space[i])
// i != start i == start
// ---------- -----------
// Minimise current.
*i = 0; // Gain = -s overwritten
// Increment the next.
++*j; // Gain = 1 1
// Adjust the first.
*start = s - 1; // Gain = s - 1 -1
// -----------------------
// Nett = 0 0
return true;
}
}
return false;
}
注意,这个算法需要在包括两端的空间和工作在过剩空间 - 也就是说,如果长度为S的空间在任一端,则S表示为S,但如果S - 1在中间的某处,则空间S表示为S,因为内部空间必须长度为1或更大。清楚的是,在这种表示中,所有空格的最小值为零。您通过将第一个空格设置为N + 1来初始化spaces
- Σ i = 0..N(长度 i + 1)并且其余N + 1个空格为0,其中N是序列的数量。
要完成故事,您需要测试给定的输入是否与给定的输入兼容,是否有给定的空格排列组合长度数组。
一个简单的方法是在开始时将输入转换为位集。然后将每个空间排列与长度数组一起转换为一个bitset并从输入bitset中减去。如果结果为空,则输入有效。
警告:我对上述算法进行了相当仔细的分析,但是我对代码做了很少的测试。下面是我写的一个相当难看的试车手,在情况下,它可以帮助你自己的测试:
template <typename T, int N>
bool next(T (&spaces)[N])
{
return next(spaces, spaces + N);
}
const char* x(int n) { return "XXXXXXXXXX" + 10 - n; }
const char* s(int n) { return "----------" + 10 - n; }
int main(int argc, const char* argv[])
{
int spaces[] = { 4, 0, 0, 0 };
do
{
// I reverse the spaces to make segments shuffle left-to-right.
// This is a purely aesthetic thing. The order of permutations
// doesn't matter.
std::cout << s(spaces[3]) << x(2)
<< s(spaces[2] + 1) << x(1)
<< s(spaces[1] + 1) << x(1)
<< s(spaces[0])
<< "\n";
}
while (next(spaces));
}
什么你尝试这么远吗?您可以与我们分享的任何代码? – Bart
你必须处理用户输入“有效”的所有可能组合,意味着什么? – leo
@Bart我没有任何代码,我真的只是试图从概念上思考这个问题,而且我很难找到任何真正开始的方法 – user1038665