ChenGen

          一切歸零,重新開始
          隨筆 - 13, 文章 - 10, 評(píng)論 - 21, 引用 - 0
          數(shù)據(jù)加載中……

          復(fù)習(xí)回溯算法——N皇后問(wèn)題

          ???今天復(fù)習(xí)了回溯算法。N皇后問(wèn)題是一個(gè)典型的需要用回溯算法來(lái)解決的問(wèn)題。回溯算法可以用遞歸方法來(lái)實(shí)現(xiàn),也可以用非遞歸方法來(lái)實(shí)現(xiàn)。用遞歸的方法來(lái)解決回溯的問(wèn)題思路很清晰,但是耗費(fèi)的內(nèi)存資源較多,速度也較慢;非遞歸方法具有速度快和耗費(fèi)較少內(nèi)存資源的優(yōu)點(diǎn),但是程序的邏輯結(jié)構(gòu)卻很復(fù)雜——不過(guò)搞懂之后覺(jué)得也很簡(jiǎn)單。

          ???在寫非遞歸算法之前,參考了網(wǎng)上的一些文章,但是覺(jué)得那些程序都很晦澀難懂,而且存在一些問(wèn)題,我索性自己寫了一個(gè),花了我不少時(shí)間。

          ???遞歸實(shí)現(xiàn):
          #include?"stdio.h"
          #include?
          "stdlib.h"
          #include?
          "time.h"

          /*?記錄當(dāng)前的放置方案?*/
          int?*x;?
          /*?皇后的個(gè)數(shù)N?和?方案數(shù)目?*/
          int?n,sum=0;
          /*?檢查參數(shù)所指示的這一行皇后放置方案是否滿足要求?*/
          int??Place(int);
          /*?遞歸方法求取皇后放置方案*/
          void?Queen1(void);
          /*?用戶遞歸求取皇后放置方案的遞歸方法?*/
          void?TraceBack(int);
          /*?打印當(dāng)前成功的放置方案?*/
          void?PrintMethod(void);

          void?main(void)
          {
          ????
          long?start,stop;
          ????printf(
          "input?n:?");
          ????scanf(
          "%d",&n);
          ????x
          =(int?*)malloc(sizeof(int)*n);
          ????time(
          &start);/*記錄開始時(shí)間*/
          ????Queen1();
          ????time(
          &stop);/*記錄結(jié)束時(shí)間*/
          ????printf(
          "\nmethod?total?%d?\n",sum);
          ????printf(
          "\nuse?%d?seconds?\n",(int)(stop-start));
          }


          int?Place(int?r)
          {
          ????
          int?i;
          ????
          for(i=0;i<r;i++){
          ????????
          if(x[r]==x[i]?||?abs(r-i)==abs(x[r]-x[i]))
          ????????????
          return?0;
          ????}

          ????
          return?1;
          }


          void?TraceBack(int?r)
          {
          ????
          int?i;
          ????
          if(r>=n){
          ????????sum
          ++;
          ????????
          /*?PrintMethod();?*/
          ????}
          else{
          ????????
          for(i=0;i<n;i++){
          ????????????x[r]
          =i;
          ????????????
          if(Place(r))?TraceBack(r+1);
          ????????}

          ????}

          }


          void?PrintMethod(void)
          {
          ????
          int?i,j;
          ????printf(
          "\nmethod?%d\n",sum);
          ????
          for(i=0;i<n;i++){
          ????????
          for(j=0;j<n;j++){
          ????????????
          if(j==x[i])?printf("*");
          ????????????
          else?printf("#");
          ????????}

          ????????printf(
          "\n");
          ????}

          }


          void?Queen1(void)
          {
          ????TraceBack(
          0);
          }

          ???非遞歸實(shí)現(xiàn):

          #include?"stdio.h"
          #include?
          "stdlib.h"
          #include?
          "time.h"

          /*?記錄當(dāng)前的放置方案?*/
          int?*x;?
          /*?皇后的個(gè)數(shù)N?和?方案數(shù)目?*/
          int?n,sum=0;
          /*?檢查參數(shù)所指示的這一行皇后放置方案是否滿足要求?*/
          int??Place(int);
          /*?非遞歸的方法求取皇后放置方案?*/
          void?Queen2(void);
          /*?打印當(dāng)前成功的放置方案?*/
          void?PrintMethod(void);

          void?main(void)
          {
          ????
          long?start,stop;
          ????printf(
          "input?n:?");
          ????scanf(
          "%d",&n);
          ????x
          =(int?*)malloc(sizeof(int)*n);
          ????time(
          &start);/*記錄開始時(shí)間*/
          ????Queen2();
          ????time(
          &stop);/*記錄結(jié)束時(shí)間*/
          ????printf(
          "\nmethod?total?%d?\n",sum);
          ????printf(
          "\nuse?%d?seconds?\n",(int)(stop-start));
          }


          int?Place(int?r)
          {
          ????
          int?i;
          ????
          for(i=0;i<r;i++){
          ????????
          if(x[r]==x[i]?||?abs(r-i)==abs(x[r]-x[i]))
          ????????????
          return?0;
          ????}

          ????
          return?1;
          }


          void?Queen2(void)
          {
          ????
          int?i,k;
          ????
          for(i=0;i<n;i++)
          ????????x[i]
          =0;
          ????k
          =0;
          ????
          while(1){
          ????????
          if(x[k]>=n){
          ????????????
          /*?如果當(dāng)前第K行的放置位置超出了范圍,那么檢查該行是否為第0行
          ???????????????如果是第0行,說(shuō)明所有的方案都已經(jīng)遍歷完畢,函數(shù)返回;否則回退到前一行
          ????????????
          */

          ????????????
          if(k==0)?break;
          ????????????x[k]
          =0;?/*?下次遍歷的初始位置?*/
          ????????????k
          --;?/*?返回上一行?*/
          ????????????x[k]
          ++;?/*下一種放置方案*/
          ????????}

          ????????
          else?if(!Place(k)){
          ????????????
          /*?如果當(dāng)前第K行的放置方案不滿足要求,采取下一種放置方案*/
          ????????????x[k]
          ++;
          ????????}

          ????????
          else{
          ????????????
          if(k==(n-1)){
          ????????????????
          /*?如果已經(jīng)是最后一行,那么表示已經(jīng)成功得到一種放置方案*/
          ????????????????sum
          ++;
          ????????????????
          /*?PrintMethod();?*/
          ????????????????x[k]
          =0;?/*下次遍歷的初始位置*/
          ????????????????k
          --;?/*返回上一行*/
          ????????????????x[k]
          ++;?/*下一種放置方案*/
          ????????????}
          else
          ????????????????k
          ++;?/*?否則開始配置下一行的皇后?*/
          ????????}

          ????}

          }


          void?PrintMethod(void)
          {
          ????
          int?i,j;
          ????printf(
          "\nmethod?%d\n",sum);
          ????
          for(i=0;i<n;i++){
          ????????
          for(j=0;j<n;j++){
          ????????????
          if(j==x[i])?printf("*");
          ????????????
          else?printf("#");
          ????????}

          ????????printf(
          "\n");
          ????}

          }


          ???兩種方法的性能比較:

          N

          遞歸算法所用時(shí)間(秒)

          非遞歸算法所用時(shí)間(秒)

          13

          6

          6

          14

          37

          35

          15

          267

          254

          ???從上面的數(shù)據(jù)可以看出,兩種方法所用的時(shí)間相差并不大,但是遞歸算法所耗用的內(nèi)存空間要比非遞歸算法大得多。因?yàn)槲疫€不知道如何檢測(cè)應(yīng)用程序所用的內(nèi)存空間的大小,所以無(wú)法給出準(zhǔn)確的證明。

          ?

          ?

          ?

          posted on 2006-09-27 22:11 ChenGen 閱讀(6812) 評(píng)論(6)  編輯  收藏 所屬分類: 數(shù)據(jù)結(jié)構(gòu)復(fù)習(xí)

          評(píng)論

          # re: 復(fù)習(xí)回溯算法——N皇后問(wèn)題  回復(fù)  更多評(píng)論   

          在嗎?加個(gè)友情鏈接啊,以后復(fù)習(xí)算法就來(lái)找你!
          2006-09-27 22:31 | 壞男孩

          # re: 復(fù)習(xí)回溯算法——N皇后問(wèn)題  回復(fù)  更多評(píng)論   

          @壞男孩
          有什么算法方面的問(wèn)題的話,可以發(fā)郵件給我,很樂(lè)意為大家解決算法的問(wèn)題~
          2006-09-27 22:43 | ChenGen

          # re: 復(fù)習(xí)回溯算法——N皇后問(wèn)題  回復(fù)  更多評(píng)論   

          。。。你的遞歸算法不用回溯?
          2008-09-24 11:01 | sw

          # re: 復(fù)習(xí)回溯算法——N皇后問(wèn)題[未登錄](méi)  回復(fù)  更多評(píng)論   

          @sw
          這是非遞歸算法
          2008-10-05 17:35 | chengen

          # re: 復(fù)習(xí)回溯算法——N皇后問(wèn)題  回復(fù)  更多評(píng)論   

          你的遞歸實(shí)現(xiàn)有問(wèn)題吧?
          2009-09-01 11:17 | 啊啊啊

          # re: 復(fù)習(xí)回溯算法——N皇后問(wèn)題[未登錄](méi)  回復(fù)  更多評(píng)論   

          用數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)五皇后問(wèn)題,你有代碼嗎
          2012-06-20 23:54 | su
          主站蜘蛛池模板: 苏尼特左旗| 东乌珠穆沁旗| 平遥县| 陇川县| 赣州市| 德保县| 云浮市| 梅州市| 漯河市| 沙洋县| 普格县| 玛曲县| 庆城县| 阿克苏市| 灵丘县| 固原市| 临夏县| 雷州市| 江西省| 双鸭山市| 陕西省| 辉南县| 沾益县| 满城县| 建阳市| 海口市| 肃北| 闵行区| 遂宁市| 崇信县| 黎城县| 双鸭山市| 上高县| 郯城县| 遂溪县| 湘潭市| 淄博市| 绩溪县| 绥化市| 长治县| 榆林市|