八皇后(c++启发式函数求解)

八皇后问题是回溯算法的典型案例,在回溯法中,经常是盲目搜索,耗费过多的搜索时间。在本次实验中,使用了启发式搜索,搜索时不是任取一个分支,而是选择最佳的分支往下搜索。经过定义状态空间、操做规则、搜索策略,咱们能够清晰快速地获得原问题的一个解。ios

八皇后问题是一个以国际象棋为背景的问题:如何可以在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都没法直接吃掉其余的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。经过计算机编程,咱们能够快速地求出问题的解。算法

状态空间

(i,C[i]), i = 0,1,…,7; (i,C[i])表示第i行的皇后放置在第C[i]列。 初始状态为C[i] = -1, i = 0,1,…,7;表示全部行都不放置皇后。 目标状态为C[i] != -1, i = 0,1,…,7;表示全部行都已经放置了皇后。

操做规则



第一个皇后放在第一行; 第二个皇后放在第二行且不与第一个皇后在同一列或对角线的空格上; …… 第i个皇后放在第i行且不与前面i-1个皇后在同一列或对角线的空格上。

搜索策略

因为在某一步放置某个皇后时,可能有多个空格能够使用,因此定义启发式函数:

   fx = 剩下未放行中可以用来放皇后的空格数

若是第i行的皇后放在第j列合法,计算启发式函数的值fx(i,j)。计算出第i行全部空格的fx后,将第i个皇后放到第i行中那个与前面i-1个皇后不在同一列或对角线上且fx值最大的空格中(相同时取第一个)。 若是当前策略没法求解,则回溯至上一步,选择fx值次大的空格放置皇后,依次类推,直至找到一个合法的解。
#include<stdio.h> #include <cstdio> #include<string> #include<math.h> #include<stdlib.h> #include<set> #include<map> #include<vector> #include<queue> #include<string.h> #include<algorithm> #include<iostream> #include<time.h> #include<list>
using namespace std; const int n=8; int c[8];  //c[i]表示第i行的皇后放在第c[i]列
int fx[8][8];  //fx[i][j]表示在i行j列放置皇后后,剩下行中能够放Q的空格数
int ansflag=0; //标记是否已经找到答案
int vis[3][16];  //vis[0][j]表示第j列有无皇后,vis[1][i+j]表示对角线/上的和相同),vis[2][i-j+n]表示对角线\上的差相同,+n避免负数 //启发式函数f():找到剩下行能够放Q的空格数
int f(int row) { int cnt=0; for(int i=row+1;i<n;i++) { for(int j=0;j<n;j++) { if(!vis[0][j]&&!vis[1][i+j]&&!vis[2][i-j+n]) cnt++; } } return cnt; } void search(int cur) { if(cur==n) ansflag++;  //全部行都合法的放置了Q,结束
    else { int flag=0;  //标志该行是否能够放置皇后
        for(int i=0;i<n;i++)  //对于cur行的每一个空格进行测试
 { if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]) { flag=1;  //[cur][i]处能够放置Q
                 c[cur]=i; vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1; fx[cur][i]=f(cur);  //计算启发式函数
                 vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0; } } if(flag)   //标志该行能够放置皇后
 { while(!ansflag) { int max=-1; int col=-1;     //记录fx最大的列
                for(int i=0;i<n;i++) //找fx最大的列
 { if(fx[cur][i]>max) { max=fx[cur][i]; col=i; } } if(max==-1) //在本行任一空格放置皇后都没法求解,回溯
 { fx[cur-1][c[cur-1]]=-1;  //将原来的最大值置为-1,那么下一次回溯找的是次大值。
                    return; } c[cur]=col;   //找到fx最大的列,放置皇后,搜索下一行。
                vis[0][col]=vis[1][cur+col]=vis[2][cur-col+n]=1; search(cur+1); vis[0][col]=vis[1][cur+col]=vis[2][cur-col+n]=0; } } else   //标志该行不能够放置皇后
            fx[cur-1][c[cur-1]]=-1; } } int main() { memset(c,-1,sizeof(c)); memset(fx,-1,sizeof(fx)); memset(vis,0,sizeof(vis)); search(0); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(j==c[i]) cout<<"Q"<<' '; else cout<<"X"<<" "; } cout<<endl; } }

解对应的棋盘: 
Q X X X X X X X 
X X X X X Q X X 
X X X X X X X Q 
X X Q X X X X X 
X X X X X X Q X 
X X X Q X X X X 
X Q X X X X X X 
X X X X Q X X X编程

相关文章
相关标签/搜索