八皇后问题

来源:互联网 发布:施耐德plc编程电缆 编辑:程序博客网 时间:2024/05/02 03:06

八皇后问题: 在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击, 即任意两个皇后都不能处于同一行、同一列或同一斜线(45度)上, 问有多少种摆法。

由已知条件可知,

每行有且只有一个皇后。用一个一维数组存放每行上皇后的位置。 

此数组中,下标表示行数,元素表示列数(也即本行上皇后的位置)。

从第一行开始遍历每行不产生冲突的皇后位置。 

当第i行没有正确位置可以放的话,那么将第i-1行的皇后位置往后移一个位置并判断是否是正确位置。 

如果i-1行还没有的话再往上找。(回溯思想) 

如果遍历到最后一行的皇后也有正确位置可以摆放的话,将其打印下来,摆法加1。 

然后继续遍历最后一行是否有其他位置也是正确的,如果有,打印下来,摆法加1; 

如果没有再去找倒数第二行上面是否有其他正确位置可以放,有的话,就再遍历最后一行,查找是否有正确位置。(回溯的思想)。


1.迭代回溯

#include <iostream>  using namespace std;    int sum=0;    bool IsValid(int a[], int rowNum)  {    for (int i = 1; i < rowNum; i++)      {          if (a[i] == a[rowNum] || abs(i - rowNum) == abs(a[i] - a[rowNum]))              return false;      }      return true;  }    void iterative_backtracking(int a[], int n)//迭代回溯  {a[1]=0;int rowNum = 1;      while (rowNum > 0)      {a[rowNum] += 1;//当前列加1的位置开始搜索          while ((a[rowNum] <= n) && !IsValid(a, rowNum))//当前列位置是否满足条件              a[rowNum] += 1;//不满足条件,继续搜索下一个位置            if (a[rowNum] <= n)//存在满足条件的列          {              if (rowNum == n)//是最后一个皇后,完成搜索              {                  for (int i = 1; i <= n; i++)                      cout << "[" << i << "," << a[i] << "]" <<" ";                  cout << endl;                  sum++;              }              else//不是,则处理下一个皇后              {                  rowNum++;                  a[rowNum] = 0;              }          }          else//回溯          {              rowNum--;          }        }  }    int main()  {int n;cout << "输入皇后个数: ";cin >> n;int *a = new int[n + 1];cout << "排列结果如下: " << endl;    iterative_backtracking(a, n);      cout << "共" << sum << "组" << endl;return 0;}  
2.递归回溯
#include <iostream>using namespace std;int sum = 0;void Print(int a[], int nNum){for (int i = 1; i <= nNum; i++)cout << "[" << i << "," << a[i] << "]" << " ";cout << endl;}bool IsValid(int a[], int rowNum){int i;for(i = 1; i < rowNum; i++){if (a[i] == a[rowNum] || abs(i - rowNum) == abs(a[i] - a[rowNum]))return false;}return true;}void PlaceQueen(int a[], int rowNum, int nNum)//递归回溯{int i = 0;if( rowNum > nNum){/*for (i = 1; i <= nNum; i++)cout << "[" << i << "," << a[i] << "]" << " ";cout << endl;*/Print(a, nNum);sum++;}else{for (i = 1; i <= nNum; i++){a[rowNum] = i;if (IsValid(a, rowNum))PlaceQueen(a, rowNum + 1, nNum);}}//return sum;}int main(){cout << "please input the number of queens: ";int n;cin >> n;int *a = new int[n + 1];cout << "the result of " << n << " queens is :" << endl;PlaceQueen(a, 1, n);cout << "There are " << sum << " groups." << endl;return 0;}

回溯法(backtracking)采用试错的思想,它尝试分步的去解决一个问题。

在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。

回溯法通常用最简单的递归方法来实现,在反复重复上述的步骤后可能出现两种情况:

  • 找到一个可能存在的正确的答案
  • 在尝试了所有可能的分步方法后宣告该问题没有答案

在最坏的情况下,回溯法会导致一次复杂度为指数时间的计算。

八皇后问题是应用回溯法求解的典型案例,可以应用到n皇后。


Reference:

http://blog.csdn.net/archimedes_zht/article/details/2306654

http://blog.csdn.net/cxllyg/article/details/8055596

原创粉丝点击