首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 其他相关 >

从八皇后开始求排列组合

2012-11-26 
从8皇后开始求排列组合对于金典的8皇后大家肯定能给出以下解法#include stdio.h #include math.h #inc

从8皇后开始求排列组合

对于金典的8皇后大家肯定能给出以下解法

#include <stdio.h>

#include <math.h>

#include <stdlib.h>

 

int sum=0;/*记录方案的个数*/

 

int Place(int k,int *x)

/*判断新加入的皇后所在的位置 k 是否与其他皇后的位置冲突,此函数用来作为是否进行剪枝的判断条件*/

{

         intj;

         for(j=1;j<k;j++)

                   if((abs(k-j) == abs(x[j]-x[k])) || (x[j]==x[k]) )/*x[i]表示皇后 i 放在棋盘的第 i 行的第x[i]列*/

                            return0;/*能攻击到其他皇后,返回 0 */

         return1;/*不能攻击到其他皇后,返回 1 */

}

 

void Backtrack(int t,int n,int *x)

/*递归回溯求解*/

{

         inti;

         if(t>n)

         {

                   sum++;

/*输出一个方案*/

                   printf("方案%d:",sum);

                   for(i=1;i<=n;i++)

                   printf("(%d,%d)",i,x[i]);

                   printf("\n");

         }

         else

         {

                   for(i=1;i<=n;i++)

                   {

                            x[t]=i;

                            if(Place(t,x))Backtrack(t+1,n,x);/*如果新加入第t个皇后所在的位置 i 没有与其他皇后的位置冲突,则进入解空间子树,试探第t+1个皇后的位置;否则不进入子树,舍弃该段子树,即进行剪枝*/

                   }

         }

}

 

main()

{

         intn,*x;

         inti;

         printf("请输入皇后的个数:");

         scanf("%d",&n);

         x=(int*)malloc((n+1)*sizeof(int));/*x[0]未使用*/

         printf("以下每个方案都表示出了%d个皇后在棋盘上的坐标\n\n",n);

         Backtrack(1,n,x);/*求解*/

         printf("总共有%d种方案\n",sum);

}

 

以代码改成n皇后也是非常容易的。把搜索的过程画成一棵子树是比较容易理解的。

然后,上面代码的本质是一个递归过程。在这个递归的过程中,我们可以看出一个问题,就是把前面几个皇后的序列放在x中,于是,我们修改代码如下就可以输入n个数的所有排列。

#include <stdio.h>

#include <math.h>

#include <stdlib.h>

 

int sum=0;/*记录方案的个数*/

 

int Place(int k,int *x)

/*判断新加入的皇后所在的位置 k 是否与其他皇后的位置冲突,此函数用来作为是否进行剪枝的判断条件*/

{

         intj;

         for(j=1;j<k;j++)

                   if((x[j]==x[k]))/*x[i]表示皇后 i 放在棋盘的第 i 行的第x[i]列*/

                            return0;/*能攻击到其他皇后,返回 0 */

         return1;/*不能攻击到其他皇后,返回 1 */

}

 

void Backtrack(int t,int n,int *x)

/*递归回溯求解*/

{

         inti;

         if(t>n)

         {

                   sum++;

/*输出一个方案*/

                   printf("方案%d:",sum);

                   for(i=1;i<=n;i++)

                   printf("(%d,%d)",i,x[i]);

                   printf("\n");

         }

         else

         {

                   for(i=1;i<=n;i++)

                   {

                            x[t]=i;

                            if(Place(t,x))Backtrack(t+1,n,x);/*如果新加入第t个皇后所在的位置 i 没有与其他皇后的位置冲突,则进入解空间子树,试探第t+1个皇后的位置;否则不进入子树,舍弃该段子树,即进行剪枝*/

                   }

         }

}

 

int main()

{

         intn,*x;

         inti;

         printf("请输入皇后的个数:");

         scanf("%d",&n);

         x=(int*)malloc((n+1)*sizeof(int));/*x[0]未使用*/

         printf("以下每个方案都表示出了%d个皇后在棋盘上的坐标\n\n",n);

         Backtrack(1,n,x);/*求解*/

         printf("总共有%d种方案\n",sum);

}

同样的,我们可以修改函数使其输入n个数中m个数的组合。代码如下:

#include <stdio.h>

#include <math.h>

#include <stdlib.h>

 

int sum=0;/*记录方案的个数*/

int m;

int Place(int k,int *x)

         /*判断新加入的皇后所在的位置k 是否与其他皇后的位置冲突,此函数用来作为是否进行剪枝的判断条件*/

{

         return1;/*不能攻击到其他皇后,返回 1 */

}

 

void Backtrack(int t,int n,int *x,intitotalbit)

         /*递归回溯求解*/

{

         inti;

         if(itotalbit>m)

                   return;

         if(t>n)

         {     

                   printf("Ok");

                   if(itotalbit<m)

                            return;

                   sum++;

                   /*输出一个方案*/

                   printf("方案%d:",sum);

                   for(i=1;i<=n;i++)

                            if(x[i])

                                     printf("%d",i);

                   printf("\n");

         }

         else

         {

                   for(i=0;i<2;i++)

                   {

                            x[t]=i;

                            if(Place(t,x))Backtrack(t+1,n,x,itotalbit+i);/*如果新加入第t个皇后所在的位置 i 没有与其他皇后的位置冲突,则进入解空间子树,试探第t+1个皇后的位置;否则不进入子树,舍弃该段子树,即进行剪枝*/

                   }

         }

}

 

int main()

{

         intn,*x;

         inti;

         printf("请输入数的个数和你要取的个数");

         scanf("%d%d",&n,&m);

         x=(int*)malloc((n+1)*sizeof(int));/*x[0]未使用*/

         Backtrack(1,n,x,0);/*求解*/

         printf("总共有%d种方案\n",sum);

}

热点排行