+ -
当前位置:首页 → 问答吧 → 大赛一个关于纸牌排列问题,求各位帮助。用C/C++实现

大赛一个关于纸牌排列问题,求各位帮助。用C/C++实现

时间:2011-09-13

来源:互联网

1.Cards 
Tom 手上有N张纸牌,每张牌都有唯一的编号,编号由1到N。一开始纸牌叠放在一
起,按编号小的在上大的在下。整副牌放在C处,然后Tom每次拿起最上面的牌,然后放
在B处或A处,在此期间,Tom还可以将B处最上面的牌放到A处。最后,所有的牌都到
了A处。若顺序不同,则最后A处的牌的排列是不一样的。 
例如,有三张牌,通过以下步骤,最后从上到下的排列为:2 3 1 
Tom很想知道到底能产生多少种排列,于是他叫你帮忙。 
Input: 
每行为一个正整数N( N <= 10 ),表示纸牌的数目。N = 0表示结束 
Output: 
对于每个N,将所有可以产生的纸牌的排列显示出来,一个排列是A处纸牌由顶到底
的顺序。将所有的排列按词典顺序输出,然后输出一行空行。注意!一个排列中,编号之间
有一个空格,而最后一个编号之后是没有空格的! 
 
Sample input: 



Sample output: 

1 2 3 
1 3 2 
2 3 1 
3 1 2 
3 2 1 

作者: a8639197   发布时间: 2011-09-13

为A B C开设 3 个栈,分别是 StackA StackB StackC;
再设一个栈集合 StackSet;
算法初始化:把 N,N-1,...,3,2,1 压入 StackC;把 StackA StackB 和 StackSet 置空;
调用 Doit();
输出 StackSet;
算法结束.

核心算法如下:
void Doit()
{
  int i,x;

  if (StackC 为空)
  {
  令 StackB 有 m 个元素;
  for (i=1;i<=m;i++)
  {
  从 StackB 弹出元素,送入 x;
  把 x 压入 StackA;
  }
  if (StackSet 没有与 StackA 重复的元素) 把 StackA 内容放入 StackSet;
  for (i=1;i<=m;i++)
  {
  从 StackA 弹出元素,送入 x;
  把 x 压入 StackB;
  }
  }
  else
  {
  从 StackC 弹出元素,送入 x;
  把 x 压入 StackB;
  Doit();
  从 StackB 弹出元素,扔掉;

  把 x 压入 StackA;
  Doit();
  从 StackA 弹出元素,扔掉;

  if (StackB 不空)
  {
  从 StackB 弹出元素,送入 x;
  把 x 压入 StackA;
  Doit();
  从 StackA 弹出元素,扔掉;
  把 x 压入 StackB;
  }
  }
}

作者: icessl   发布时间: 2011-09-14

这个问题其实就是在问:

给你一个栈(原题目中的B),按顺序向其中 push ,随意从其中 pop 。求可能得到的所有输出队列。

首先,总的组合数是 Catalan 数(去查 wiki 和 wolfram 能够得到详细信息)。
其次,根据上面的问题“翻译”,你可以写出一个递归实现来做这件事。

BTW, Catalan 数增长的很快,这也就是限制 n<=10 的原因。你可以从参考资料中得到该数值的大小。

作者: Leaveye   发布时间: 2011-09-14

热门下载

更多