C ++中的组合

时间:2011-11-09 22:33:00

标签: c++

假设您有一个字符串向量,用于将X存储在用户指定的位置。例如,用户可以键入“X 3”,您必须告诉他们是否可以在向量中的第3个位置插入X.这就是出现问题的地方......告诉用户插入是否有效。

因此,基本上,向量分配了2个数字,每次用户运行程序时都会更改。因此,假设矢量大小为10,分配给它的数字为3,2。这意味着必须有一个3 X的运行,至少一个空间和一个2 X的运行。所以,它看起来像这样:

  

X X X _ _ _ _ X X _

在这种情况下,如果用户在X所在的任何上述位置输入X,则这将是有效的移动。但是,用户也可以这样做:

  

_ _ _ _ X X X _ X X

这也是有效的。

我的问题是:如何设置一个系统来处理有效的用户输入的所有可能组合?

请记住,矢量大小可以是任何大小。这个问题实际上是picross拼图的一部分,万一有帮助!

1 个答案:

答案 0 :(得分:1)

以下函数生成段之间空格的排列,当它不能再生成时返回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 - 1如果它位于中间的某个地方,因为内部空间必须长度为1或更长。为了清楚起见,在此表示中,所有空格的最小值都为零。通过将第一个空格设置为N + 1 - Σ i = 0..N (长度 i + 1)和剩余的N + 1来初始化spaces空格为0,其中N是序列的数量。

要完成这个故事,您需要测试任何给定的空格排列,以及长度数组是否与给定输入兼容。

一种简单的方法是在开始时将输入转换为位集。然后将每个空间排列与长度数组一起转换为位集并从输入位集减去。如果结果为空,则输入有效。

警告:我非常仔细地分析了上面的算法,但是我对代码的测试很少。这是我编写的一个相当粗糙的测试驱动程序,以防它有助于您自己的测试:

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));
}