首页
社区
课程
招聘
[原创]n辆车顺序进入一个栈开出车站可能的顺序
发表于: 2007-7-30 21:07 6448

[原创]n辆车顺序进入一个栈开出车站可能的顺序

2007-7-30 21:07
6448
//---------------------------------------------------------------------------
/*真的是一道有趣但简单的题目:
编号分别为1-n的n辆车顺序进入一个栈式结构的站台。试给出这n辆车开出车站的所有可能的顺序。

如果你看到这里就会做了,那么你比我厉害多了。我看到这里,想了一分钟,没有结果。
看到下面的提示,才……
例如编号为1,2,3,4的4辆车按照push,push,pop,push,push,pop,pop,pop操作,可使得开出车站的次序
为2,4,3,1。
原来是push和pop的排列再判断就可以了(不是车的排列)。假设push为1,而pop为0
这里假设n比较小*/
#pragma hdrstop
#include <iostream.h>
#include <windows.h>
//---------------------------------------------------------------------------
void dg();
bool pd1();
bool pd2();
void print();
int n,cn;
char car[100];
#pragma argsused
int main(int argc, char* argv[])
{
DWORD t1,t2;
t1=GetTickCount();
cn=5;n=1;
dg();
t2=GetTickCount();
cout<<t2-t1;
getchar();
        return 0;
}
//---------------------------------------------------------------------------
void dg()//递归
{char fg;
if (n==2*cn+1) exit;
else{
  for (fg=0;fg<=1;++fg)
  {
  car[n]=fg;
  if (pd1()==false) continue;//优化
  if (n==2*cn) if (pd2()) print();//终极判断
  ++n;
  dg();
  --n;
  }
  }
}
bool pd1()//判断
{int num;
int npush=0,npop=0;
for (num=1;num<=n;++num)
    {if (car[num]==1) ++npush;
        else ++npop;
     if (npop>npush) return false;
    }
    return true;
}
bool pd2()
{int num;
int npush=0,npop=0;
for (num=1;num<=2*cn;++num)
    {if (car[num]==1) ++npush;
        else ++npop;
    }
   if (npush==npop)return true;
    else return false;
}
void print()//输出
{int stack[100],n=1;
int pt=0;
int num;
for (num=1;num<=2*cn;++num)
    {
    if (car[num]==1) {++pt;stack[pt]=n;n++;}
    if (car[num]==0) {cout<<stack[pt]<<" ";--pt;}
    }
    cout<<endl;
/*for (num=1;num<=2*cn;++num) cout<<(int)car[num];
cout<<endl;*/
}
最后说一句屁话,模块化编程很重要。

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
为甚么不用stl?
#include <iostream>
#include <string>

using namespace std;

void printPopList(string& input_ls, string& stack, string& out_ls)
{
     if (out_ls.size()==4)
     {
     cout<<out_ls<<endl;
         return;
     }
     if(input_ls.size())
     {
  string my_input=input_ls;
  string my_stack=stack;
  string my_out=out_ls;
  my_stack+=my_input[0];
  my_input.erase(0,1);
  printPopList(my_input, my_stack, my_out);
     }
     if( stack.size())
     {
  string my_input=input_ls;
  string my_stack=stack;
  string my_out=out_ls;
  my_out+=my_stack[my_stack.size()-1];
  my_stack.erase(my_stack.size()-1);
  printPopList(my_input, my_stack, my_out);
     }
}

int main(){
     string input_ls="ABCD",stack(""),out("");
     printPopList(input_ls,stack,out);
     return 0;}
2007-8-1 12:04
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
3
ACM基础题
2007-8-2 21:33
0
雪    币: 443
活跃值: (200)
能力值: ( LV9,RANK:1140 )
在线值:
发帖
回帖
粉丝
4
看不懂的说!
2007-8-3 13:43
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
5
吃了顿饭解决了bug, 不用递归

/* FUCKCAR.CPP / forgot / 2007 */

#include <stdio.h>
#include <stdlib.h>

#define N         5
#define MAXBITS   ( 1 << ( 2 * N + 1 ) )
#define MAX_STACK 1000

unsigned long stack[MAX_STACK];
unsigned long sp;
unsigned long flag;

void empty( void )
{
  sp = 0;
}

void push( int x )
{
  if ( sp == MAX_STACK )
  {
    printf( "***ERROR***: stack overflow\n" );
    exit( 0 );
  }
  stack[ ++sp ] = x;
}

int pop( void )
{
  if ( sp < 0 )
  {
    return 0;
  }
  return stack[ sp-- ];
}

void dump( void )
{
  int x, npush = 0, npop = 0;

  for ( int i = 0; i < MAXBITS; i++)
  {
    if ( flag & ( 1 << i ) )
    {
      x = pop();
      if ( x == 0 ) 
      {
        npop = 0; //strip this situation
        break;
      }
      printf("%d", x);
      if ( npop++ == N ) 
        break;    // all done
    }
    else
    {
      if ( npush == N )
      {
        break;
      }
      push( ++npush );
    }
  }
  
  // if( npop == N )printf( "(flag=%08X)", flag ); //DEBUG    
  printf( npop == N ? "\n" : "\r" );    
}

int main()
{
  for ( flag = 0; flag < MAXBITS; flag += 2)
  {
    empty();
    dump();
  }
  printf("***FUCKED***\n");
  getchar();
}

/* EOF */
 
2007-8-3 14:56
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
吃了顿饭解决了bug, 不用递归

/* FUCKCAR.CPP / forgot / 2007 */

---------------------------------------------------------
握手,我写代码时也老习惯用fuck来命名.哈哈~~
2007-8-3 17:39
0
雪    币: 1946
活跃值: (243)
能力值: (RANK:330 )
在线值:
发帖
回帖
粉丝
7
代码跟楼上的差不多,不贴了.
2007-8-4 23:53
0
雪    币: 519
活跃值: (1223)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
8
看大家很有兴致,问个不是很trivial的问题,对于N辆车,这样的不同顺序共有多少种?要求给出公式(递推形式或闭合形式都可以)
2007-8-5 00:57
0
雪    币: 112
活跃值: (16)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
9
可以很简单的解出此题。具体证明如下:
      问题等价于:n个1和n个0组成一2n位的2进制数,要求从左到右扫描,1的累计数不小于0的累  
                  计数,试求满足这条件的数有多少?

解答:设P2n为这样所得的数的个数。在2n位上填入n个1的方案数为 C(n 2n)
不填1的其余n位自动填以数0。从C(n 2n)中减去不符合要求的方案数即为所求。
不合要求的数指的是从左而右扫描,出现0的累计数超过1的累计数的数。
不合要求的数的特征是从左而右扫描时,必然在某一奇数2m+1位上首先出现m+1个的累计数,和m个1的累计数。
此后的2(n-m)-1位上有n-m个1,n-m-1个0。如若把后面这部分2(n-m)-1位,0与1交换,使之成为n-m个0,n-m-1个1,结果得1个由n+1个0和n-1个1组成的2n位数,即一个不合要求的数对应于一个由n-1个0和n+1个1组成的一个排列。
反过来,任何一个由n+1个0,n-1个1组成的2n位数,由于0的个数多2个,2n是偶数,故必在某一个奇数位上出现0的累计数超过1的累计数。同样在后面的部分,令0和1互换,使之成为由n个0和n个1组成的2n位数。即n+1个0和n-1个1组成的2n位数,必对应于一个不合要求的数。
用上述方法建立了由n+1个0和n-1个1组成的2n位数,与由n个0和n个1组成的2n位数中从左向右扫描出现0的累计数超过1的累计数的数一一对应。

例如 10100101
是由4个0和4个1组成的8位2进制数。但从左而右扫描在第5位(显示为红色)出现0的累计数3超过1的累计数2,它对应于由3个1,5个0组成的10100010。
反过来 10100010
对应于 10100101
因而不合要求的2n位数与n+1个0,n-1个1组成的排列一一对应,故有
P2n = C(n 2n)— C(n+1 2n)
这个结果是一个“卡塔兰数”Catalan,在组合数学中有介绍,可以参阅有关资料。
2007-8-5 08:31
0
雪    币: 519
活跃值: (1223)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
10
Catalan数正解,呵呵
2007-8-6 22:54
0
游客
登录 | 注册 方可回帖
返回
//