文章标题

来源:互联网 发布:箪食壶浆以迎将军乎 编辑:程序博客网 时间:2024/06/07 02:24

八皇后问题

回溯法与枚举法


题目简介

八皇后问题是十九世纪著名数学家高斯于1850年提出的。问题是:在8*8的棋盘上摆放8个皇后,使其不能互相攻击,即任意的两个皇后不能处在同意行,同一列,或同意斜线上。可以把八皇后问题拓展为n皇后问题,即在n*n的棋盘上摆放n个皇后,使其任意两个皇后都不能处于同一行、同一列或同一斜线上。

解决冲突:处于同一列或者处于一条对角线上(正负对角线)
(i - j) /(a[i] - a[j]) == 1 或者 (i - j) /(a[i] - a[j]) == -1 或者 a[i] == a[j]

枚举法
思想:八重枚举,枚举出所以摆放的情况(不管合理不合理),然后到第八层for里面判断当前枚举出来的情况是否合理~~~

#include <cstdio>#include <cmath>//位置冲突算法 bool Chongtu(int a[], int n)//a[]位置数组,n皇后个数 {    int i = 0, j = 0;    for (i = 2; i <= n; ++i)//i:位置         for (j = 1; j <= i-1; ++j)//j:位置             if ((a[i] == a[j]) || (abs(a[i]-a[j]) == i-j))//1:在一行;2:在对角线上                 return false;   //冲突     return true;//不冲突 }//八皇后:枚举算法 void Queens8(){    int a[9] = {0}; //用于记录皇后位置:(第0行0列我们不用)。如:a[3] = 4;表示第3列第4行位置有皇后    int i = 0,count = 0;  //用于计数     for (a[1] = 1; a[1] <= 8; ++a[1])        for (a[2] = 1; a[2] <= 8; ++a[2])            for (a[3] = 1; a[3] <= 8; ++a[3])                for (a[4] = 1; a[4] <= 8; ++a[4])                    for (a[5] = 1; a[5] <= 8; ++a[5])                        for (a[6] = 1; a[6] <= 8; ++a[6])                            for (a[7] = 1; a[7] <= 8; ++a[7])                                for (a[8] = 1; a[8] <= 8; ++a[8])                                {                                    if (!Chongtu(a,8))//如果冲突,则继续枚举                                         continue;                                    else                                    {                                        printf("第%d情况:",++count);                                        for (i = 1; i <= 8; ++i)                                            printf("%d ",a[i]);//打印某种情况                                         printf("\n");                                    }                                }}//主函数 int main(){    Queens8();    return 0;}

回溯法(递归版):

#include <cstdio>#include <cmath>int a[9] = {0};int n = 8, count = 0;//位置冲突算法 bool Chongtu(int a[], int n)//a[]位置数组,n皇后个数 {    int i = 0, j = 0;    for (i = 2; i <= n; ++i)//i:位置         for (j = 1; j <= i-1; ++j)//j:位置             if ((a[i] == a[j]) || (abs(a[i]-a[j]) == i-j))//1:在一行;2:在对角线上                 return false;   //冲突     return true;//不冲突 }//八皇后问题:回溯算法(递归版) void Queens8(int k) //参数k:递归摆放第k个皇后 {    int i = 0;    if (k > n)      //k>n:即k>8表示最后一个皇后摆放完毕     {        printf("第%d种情况:",++count);        for (i = 1; i <= n; ++i)            printf("%d ",a[i]);//打印情况         printf("\n");    }    else   //8个皇后未全部摆放完毕            {        for (i = 1; i <= n; ++i)//摆放第k个皇后时(转下一行)         {       //依次从列顶端开始搜索,一直到列底端,直到找到合适位置,如果未找到,自动返回上层递归(回溯)             a[k] = i;                           if (Chongtu(a,k))//不冲突                 Queens8(k+1);//递归摆放下一个皇后        }    }    return;}//主函数 int main(){    Queens8(1);//参数1:表示摆放第1个皇后     return 0;} 

回溯法(非递归版):

#include <cstdio>#include <cmath>//位置冲突算法 bool Chongtu(int a[], int n)//a[]位置数组,n皇后个数 {    int i = 0, j = 0;    for (i = 2; i <= n; ++i)//i:位置         for (j = 1; j <= i-1; ++j)//j:位置             if ((a[i] == a[j]) || (abs(a[i]-a[j]) == i-j))//1:在一行;2:在对角线上                 return false;   //冲突     return true;//不冲突 }//八皇后问题:回溯法(非递归) void Queens8(){    int n = 8;        //8个皇后     int count = 0;    //记录当前第几情况     int a[9] = {0};   //存放皇后位置,如:a[2] = 4;表示第2列第4行有一个皇后(a[0]不用)     int i = 0,k = 1;  //初始化k为第一列     a[1] = 0;         //初始化a[1] = 0     while (k > 0)     //k==0时:表示摆放第1个皇后就超过了列底部(即已经找完所有情况)     {        a[k] += 1;    //a[k]位置,摆放一个皇后         while ((a[k] <= n) && (!Chongtu(a,k)))//如果a[k](即皇后摆放位置)没有到列最底部,且摆放冲突。             a[k] += 1;//将皇后列下移一位         if (a[k] <= n)//皇后摆放位置没有到达列最底部         {            if (k == n)//k==n表示,8列皇后全部摆放完毕             {                printf("第%d种情况:",++count);                for (i = 1; i <= n; ++i)//打印情况                     printf("%d ",a[i]);                printf("\n");            }            else      //皇后还未摆放完毕             {                k += 1;    //继续摆放下一列                 a[k] = 0;  //此行初始化a[k] = 0;表示第k列,从第一行开始摆放皇后             }        }        else  //回溯:当a[k]>8进入else,表示在第k列中没有找到合适的摆放位置             k -= 1;//回溯到k-1步:k表示第几个皇后,a[k]表示第k个皇后摆放的位置     }    return;}//主函数 int main(){    Queens8();    return 0;}

0 0