九连环问题解决

九连环。九连环的初始状态是九个环全部被安装在一个狭长的“梭”上,这个初始状态可以表示为:

1)(2)(3)(4)(5)(6)(7)(8)(9), 

如果终止状态是将九个环全部拆卸下来。那么终止状态可以表示为:

1】【2】【3】【4】【5】【6】【7】【8】【9】。

编写一段程序,输出拆卸九连环(从初始状态到终止状态)的操作过程,要求程序按照拆卸的步骤,顺序地输出拆卸过程中每一步的动作以及每一步操作后九连环的状态。

例如:从九连环的初始状态开始,拆卸最前面的三个环时,各步骤的动作以及每一步操作后九连环的状态如下:

步骤

动作

操作之后,九连环的状态

1

1

[1](2)(3)(4)(5)(6)(7)(8)(9)

2

3

[1](2)[3](4)(5)(6)(7)(8)(9)

3

1

1(2)[3](4)(5)(6)(7)(8)(9)

4

2

(1)[2][3](4)(5)(6)(7)(8)(9)

5

1

[1][2][3](4)(5)(6)(7)(8)(9)

 

程序设计思路:不管拆卸还是上九连环都遵守两条规则:1、第1个环可以随便上下。2在上下第n个环时第(n-1)个环必须在家在架上,而(n-2)以后的环必须在环下。拆卸九连环必先拆卸八连环,拆卸八连环先拆七连环。。。直到只剩一个环自由上下。可见拆卸九连环为一递归过程。此过程含有两个过程:上环和下环。例如:拆卸n连环,先拆卸(n-2)连环,拆卸第n环,上(n-2环,转换为拆卸(n-1)环。如此。同样在上n连环时,先上(n-1)连环拆卸(n-2)环上第n个环,转换为上(n-1)个环。上下环过程中注意取值,不然会造成无穷递归而出错。最后由于输出太长采用输出一个文件,记录拆卸步骤和九连环状态。

主要算法和代码:程序中主要有两个函数:上环函数和下环函数,其代码:

上环函数:

void MoveUp(int n)
                       {MoveUp(n-1);    //先上前n-1个环;
MoveDn(n-2);    //把前n-2个环全下了
Printf(“上%d环”,n);    //上第n环
MoveUp(n-2);     //上以后n-2个环
 };


下环函数:

voidMoveDn(int n)
                        {MoveDn(n-2);     //先下了前n-2个环
Printf(“下%d环”,n);   //下第n环
MoveUp(n-2);     //上n-2个环
MoveDn(n-1);     //下前面的n-1个环
}

  递归调用上环和下环函数。注意n的取值,不然出现无穷递归!当n=1时可自由上下。

  本题主要体现递归调用回溯的思想:第一个环自由上下,其余环按照规则上下。在程序设计调试过程中遇到了n取值没注意规定范围只定义了n=1时的特殊情况,结果出现n负值而没有结果,可见再递归过程中条件控制的重要不然出现无穷递归。   

 源代码:

#include<stdio.h>
#include<string.h>
int flag[10];
void Init(int flag[]);
int Done(int n);
void MoveDn(int n);
void MoveUp(int n);
int cishu=0;
void print(int flag[]);
FILE *fp;
 
void main()
{
 printf("输出结果在ANS.dat文件/n");
 if((fp=fopen("ANS.txt","w+"))==NULL)printf("Cannot open this file!/n");
 fprintf(fp,"   操作后,九连环的状态/t    /t步骤与动作/n");
 Init(flag);
 MoveDn(9);
    fclose(fp);
 getchar();
}
void Init(int flag[])
{
 int i;
 for(i=1;i<10;i++)
  flag[i]=0;
}

void MoveDn(int n)
{
 if(n>2) MoveDn(n-2);
 flag[n]=1; 
 print(flag);
 cishu++;
 fprintf(fp,"/t第%d步,下%d环/n",cishu,n);
 if(n>2) MoveUp(n-2);
 if(n>1) MoveDn(n-1);
}
void MoveUp(int n)
{
 if(n>1) MoveUp(n-1);
 if(n>2) MoveDn(n-2);
    flag[n]=0;
 cishu++;
    print(flag);
    fprintf(fp,"/t第%d步,上%d环/n",cishu,n);
    if(n>2) MoveUp(n-2);
}
void print(int flag[])
{
 int i=1;
 while(i<=9)
 {
  if(flag[i]==1)fprintf(fp,"[%d]",i);
  else fprintf(fp,"(%d)",i);
  i++;
 }
}


转自:http://blog.csdn.net/zhl0349/article/details/951883

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值