九連環問題解決

九連環。九連環的初始狀態是九個環全部被安裝在一個狹長的“梭”上,這個初始狀態可以表示爲:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章