八皇后问题(回溯法)

[cpp] view plain copy print ?
  1. #include<iostream>   
  2. using namespace std;  
  3.   
  4. #define N 8   
  5. //N代表皇后数   
  6. void queen()  
  7. {  
  8.     int Count=0;         //计算总共的解的数量   
  9.     int column[N+1];     //column[m]=n表示第m行,第n行放置了皇后,这里下表并从0开始   
  10.     int row[N+1];        //row[m]=1表示第m行没有皇后,=0表示有皇后   
  11.     int b[2*N+1];        //b[m]=1表示第m条主对角线没有皇后,   
  12.     int c[2*N+1];        //c[m]=1表示第m条次对角线没有皇后,=0表示有皇后   
  13.     int numQueen=1;      //计数已经放置的皇后数目,当numQueen=N时候则表示已经完成探测   
  14.     int good=1;          //good=1表示没有发生冲突,good=0表示发生冲突   
  15.       
  16.     //初始化这些标记   
  17.     for(int j=0;j<N+1;++j)  
  18.     {  
  19.         row[j]=1;  
  20.     }  
  21.     for(int j=0;j<2*N+1;++j)  
  22.     {  
  23.         b[j]=c[j]=1;  
  24.     }  
  25.     column[1]=1;  
  26.     column[0]=0;          //初始化第一行第一列,第二行第二列放置皇后   
  27.     do  
  28.     {  
  29.         //没有发生冲突,则继续向下探测,增加皇后或者判断当前是否是解   
  30.         if(good)  
  31.         {  
  32.             //当前皇后数是解,打印,继续向下探测   
  33.             if(numQueen==N)  
  34.             {  
  35.                 Count++;  
  36.                 cout<<"找到解"<<endl;  
  37.                 for(int j=1;j<N+1;++j)  
  38.                 {  
  39.                     cout<<j<<"列"<<column[j]<<"行"<<endl;  
  40.                 }  
  41.                 //最后一个棋子向下移动,移动到本列最后一个   
  42.                 while(column[numQueen]==N)  
  43.                 {  
  44.                     numQueen--;         //皇后数减1,即列数减1,回溯   
  45.                     //回溯后将该列以及该列最后一行状态位修改   
  46.                     //第numQueen列column[numQueen]行处状态位置修改   
  47.                     row[column[numQueen]]=1;  
  48.                     b[numQueen+column[numQueen]]=1;  
  49.                     c[N+numQueen-column[numQueen]]=1;  
  50.                 }  
  51.                 column[numQueen]++;     //回溯至上一行,向上一行的下一列继续探测   
  52.             }  
  53.             //当前不是解,那么继续向下探测   
  54.             else  
  55.             {  
  56.                 //改变该位置对应标志   
  57.                 row[column[numQueen]]=0;  
  58.                 b[numQueen+column[numQueen]]=0;  
  59.                 c[N+numQueen-column[numQueen]]=0;  
  60.                 //本次位置没有发生冲突,也不是正确解,那么就应该向下探测下一列的第一行   
  61.                 column[++numQueen]=1;  
  62.             }  
  63.         }  
  64.         //如果当前发生了冲突,就在本列继续向下,如果到了本列最后一行,则回溯到上一列   
  65.         else  
  66.         {  
  67.             while(column[numQueen]==N) //到了本列最后一行,还是冲突,那么回溯到上一列   
  68.             {  
  69.                 numQueen--;  
  70.                 row[column[numQueen]]=1;  
  71.                 b[numQueen+column[numQueen]]=1;  
  72.                 c[N+numQueen-column[numQueen]]=1;  
  73.             }  
  74.             column[numQueen]++; //发生冲突了,又没有到本列的最后一行,那么在本列继续向下一行探测   
  75.         }  
  76.         //检测放置了这个位置后是否冲突   
  77.         good=row[column[numQueen]]&b[numQueen+column[numQueen]]&c[N+numQueen-column[numQueen]];  
  78.     }while(numQueen);  
  79.     cout<<N<<"皇后总共找到解:"<<Count<<"个"<<endl;  
  80. }  
  81. void main()  
  82. {  
  83.     queen();  
  84.     system("pause");  
  85. }  

这种非递归方法还是比较容易理解的

 

另外还有递归方法,先来看一下递归算法的伪代码

void trial(int row)

{

     //递归时候,我们从第0行开始,然后每次递归时候,都向下一行,一直到棋盘的最后一行

     //这时候就表示已经是正确的解了,所有进入该函数首先判断是否是正确的解

     if(row>N)

    {

         //输出此时的棋盘

    }

    else

    {

        for(int i=0;i<N;++i)

        { 

             //不是解,这时候需要在本行的每一列开始试探放旗子,如果可以的话继续向下递归

             #修改记录冲突的数组

              if(放在这个位置不会冲突)

             {

                     trial(row+1);

             }

             放在这里冲突,那么修改回记录的数组,继续下一列

        }

     }

}

 

下面给出递归的

void EightQueen (int row)  
  1. {  
  2.         if(row>N)  
  3.         {  
  4.                PrintMap();    //打印棋盘   
  5.          }  
  6.         else  
  7.         {  
  8.         int column;  
  9.         for (column = 0; column < N; ++column)  
  10.         {  
  11.                 A[row]= column;                    //代表第row行的第column列放皇后   
  12.                 if (IsCorrect (row, column))    //判断在第row行的第column列放皇后是否可行   
  13.                 {  
  14.                         EightQueen (row + 1);  
  15.                 }  
  16.               //将标记数组修改回原来   
  17.         }  
  18.         }  
  19. }  

 

 

你可能感兴趣的:(八皇后问题(回溯法))