圆盘问题

本文介绍了一种解决圆盘问题的算法实现,通过输入圆盘的数量和目标序列,算法能够输出从初始状态到目标状态的操作步骤。文章提供了完整的C++代码示例,并解释了如何通过中间柱来移动圆盘。

(圆盘问题) 从左向右依次安放 4 根细柱 A,B,C,D. 在 A 上套有 N (N≤20)
 个直径相同的圆盘, 从下到上依次用连续的小写字母 a,b,c,...编号, 将这些圆盘
 经过 B, C 单向地移入 D (即不允许从右向左移动). 圆盘可在 B,C 中暂存. 从键
 盘输入 N, 及前 N 个小写字母的一个排列, 它表示最后在 D 盘上形成的一个从下
 到上的圆盘序列. 请用文本文件 ANS2.TXT 输出形成这一排列的操作过程.
   该文件的每一行为一个形如 "k M L" 的字母序列, 其中 k 为圆盘编号, M 为 k
 盘原先的柱号, L 为新柱号. 或者直接在屏幕上输出"No",表示不能生成这种排列.
     例:                                ┃      ┃      ┃      ┃
     键盘输入:                          ┃      ┃      ┃      ┃
         3                        d   ━╋━    ┃      ┃      ┃
         acb                      c   ━╋━    ┃      ┃      ┃
     则一个正确的输出文件         b   ━╋━    ┃      ┃      ┃
  可以是:                         a   ━╋━    ┃      ┃      ┃
      c  A  B                       ━━┻━━━┻━━━┻━━━┻━
      b  A  C                           A       B       C       D
      a  A  D
      c  B  D       b  C  D    

代码:

#include <iostream.h>


void change(char *A,char *B,char *C,char *D,int num);


void print(char a,char *b,char *c)
{
 cout<<a<<"  "<<b[0]<<"  "<<c[0]<<endl;
}


int is_last(char **m_ptr,int &a,int &b,int &c,int &d)
{
 if(a!=0&&(m_ptr[0][a]==m_ptr[3][d]))
 {
  print(m_ptr[3][d],m_ptr[0],m_ptr[3]);
  a--;d++;
  return 1;
 }
 if(b!=0&&(m_ptr[1][b]==m_ptr[3][d]))
 {
  print(m_ptr[3][d],m_ptr[1],m_ptr[3]);
  b--;d++;
  return 2;
 }
 if(c!=0&&(m_ptr[2][c]==m_ptr[3][d]))
 {
  print(m_ptr[3][d],m_ptr[2],m_ptr[3]);
  c--;d++;
  return 3;
 }
 return 0;
}

 


int main()
{
 char A[21]={'A'},B[21]={'B'},C[21]={'C'},D[21]={'D'};
 int num_circle;
 cout<<"please input the number of circle:"<<endl;
 cin>>num_circle;
 cout<<"please input the order:"<<endl;
 cin>>&D[1];
    change(A,B,C,D,num_circle);
 //cout<<A<<endl;
 //cout<<D<<endl;
 return 0;
}

void change(char *A,char *B,char *C,char *D,int num)
{
 //初始化
 char * ptr[]={A,B,C,D};
 int num_a=num,num_b=0,num_c=0,num_d=1;     //指向A,B,C,D
 for(int i=0;i<num;i++)    
  A[i+1]='a'+i;
 
 //开始移动
   
 while(num_a!=0)              //处理A上的盘子
 {
  while(is_last(ptr,num_a,num_b,num_c,num_d))
  {
   is_last(ptr,num_a,num_b,num_c,num_d);
  }
  int i=num,j=num,k=num;
  for(;num_a!=0&&ptr[0][num_a]!=ptr[3][i];i--)
   ;
  for(;num_b!=0&&ptr[1][num_b]!=ptr[3][j];j--)
   ;
  for(;num_c!=0&&ptr[2][num_c]!=ptr[3][k];k--)
   ;
  if(i<j)
  {
   ptr[1][++num_b]=ptr[0][num_a--];
   print(ptr[1][num_b],ptr[0],ptr[1]);
  }
  else if(i>j&&i<=k)
  {
   ptr[2][++num_c]=ptr[0][num_a--];
   print(ptr[2][num_c],ptr[0],ptr[2]);
  }
  else break;
  i=num;j=num;k=num;
 }
    if(num_a!=0)
  cout<<"impossible!"<<endl;
 else
 {
  for(;num_d!=num;)
  {
   if(ptr[1][num_b]==ptr[3][num_d])
   {
    print(ptr[3][num_d],ptr[1],ptr[3]);
    num_b--;num_d++;
   }
   if(ptr[2][num_c]==ptr[3][num_d])
   {
    print(ptr[3][num_d],ptr[2],ptr[3]);
    num_c--;num_d++;
   }

  }
 }
 
 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值