八皇后——回溯法
八皇后问题(英文:Eight queens),是由国际象棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。
1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。
计算机发明后,有多种计算机语言可以编程解决此问题。
问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。
思路:每一行、一列、左斜、右斜都只能放置一个皇后,那么可以用一个数组attack表示当前可以放置的位置,(数组queen存储答案)每放置一个皇后就在她所在的行、列、左斜、右斜都进行标志,如果行、列、左斜、右斜任意一个已被标志,那么就改变皇后位置继续进行比较,直到可以放置或当前列没有位置后进行回溯
代码求解:
#include<bits/stdc++.h> using namespace std; //实现在(x,y)放置皇后,对attack数组的更新 //x,y表示放置皇后的坐标,二维数组attack表示棋盘是否可放置皇后 void put_queen(int x,int y,vector<vector<int>>&attack){ //dx,dy是方向数组,方便后面对8个方向进行标记 static const int dx[]={-1,1,0,0,-1,-1,1,1}; static const int dy[]={0,0,-1,1,-1,1,-1,1}; attack[x][y]=1;//将皇后位置标记为1 //通过两层循环,将该皇后可能攻击到的位置进行标记 for(int i=1;i<attack.size();i++){//从皇后位置向1到n-1个距离延伸 for(int j=0;j<8;j++){//遍历8个方向 int nx=x+i*dx[j];//生成的新位置行 int ny=y+i*dy[j];//生成的新位置列 //新位置在棋盘范围内 if(nx>=0&&nx<attack.size()&&ny>=0&&ny<attack.size()){ attack[nx][ny]=1;//将新位置标记为1 } } } } //回溯法求解N皇后的递归函数 //k表示当前处理的行 //n表示N皇后问题 //queen存储皇后的位置 //attack标记皇后的攻击位置 //solve存储N皇后的全部解法 void backtrack(int k,int n,vector<string>&queen,vector<vector<int>>&attack,vector<vector<string>>&solve){ if(k==n){//找到一组解 solve.push_back(queen);//将结果queen存储至solve return;//返回 } //遍历0至n-1列,在循环种,回溯试探皇后可知放置的位置 for(int i=0;i<n;i++){ if(attack[k][i]==0){//判断当前第k行第i列是否可以放置皇后 vector<vector<int>> tmp=attack;//备份attack数组 queen[k][i]='Q';//标记该位置为'Q' put_queen(k,i,attack);//更新attack数组 backtrack(k+1,n,queen,attack,solve);//递归试探k+1行的皇后放置 attack=tmp;//恢复attack数组 queen[k][i]='.';//恢复queen数组 } } } vector<vector<string>> solveNQueens(int n){ vector<vector<string>>solve;//存储最后结果 vector<vector<int>>attack;//标记皇后的攻击位置 vector<string> queen;//保存皇后位置 //使用循环初始化attack和queen数组 for(int i=0;i<n;i++){ attack.push_back(std::vector<int>()); for(int j=0;j<n;j++) attack[i].push_back(0); queen.push_back(""); queen[i].append(n,'.'); } backtrack(0,n,queen,attack,solve);//调用backtrack求解N皇后问题 return solve;//返回结果数组solve } int main(){ vector<vector<string>>result; result=solveNQueens(8); //打印出8皇后的解法 cout<<"8皇后共有"<<result.size()<<"种解法:"<<endl; for(int i=0;i<result.size();i++){ cout<<"解法"<<i+1<<":"<<endl; for(int j=0;j<result[i].size();j++) cout<<result[i][j].c_str()<<endl; cout<<endl; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?