算法设计(一) : 搜索算法实现八皇后问题

article/2025/9/15 9:50:28

写在开头:实验结果截图8皇后太多截不完,用4皇后代替了,只需将n->8就行

目录

图解算法过程:

在这里插入图片描述
下面分析中的 ( x , y ) (x,y) (x,y)相当于上面的 ( u , i ) (u,i) (u,i)
反对角线 y = x + b y=x+b y=x+b, 截距 b = y − x b=y−x b=yx,因为我们要把 b b b 当做数组下标来用,显然 b b b 不能是的,所以我们加上 n (实际上 + n + 4 +n+4 +n+4, + 2 n +2n +2n都行),来保证是结果是正的,即 y − x + n y - x + n yx+n
而对角线 y = − x + b y=−x+b y=x+b 截距是 b = y + x b=y+x b=y+x,这里截距一定是的,所以不需要加偏移量
核心目的:找一些合法的下标来表示dgudg是否被标记过,所以如果你愿意,你取 udg[n−u+i] 也可以,只要所有(u,i)对可以映射过去就行

算法一:DFS 按行枚举,时间复杂度O(n!)

const int N=25;
int n;
char g[N][N];
bool dg[N],udg[N],col[N];//对角线 dg[u+i],反对角线udg[n−u+i]中的下标 u+i和 n−u+i 表示的是截距
int k=1;
void dfs(int u)
{if(u==n){cout<<n<<"皇后的第"<<k++<<"种方案:"<<endl;for(int i=0;i<n;i++)cout<<g[i]<<endl;cout<<endl;return; }for(int i=0;i<n;i++){if(!col[i]&&!dg[u+i]&&!udg[n-u+i]){g[u][i]='Q';col[i]=dg[u+i]=udg[n-u+i]=true;//标记 dfs(u+1);col[i]=dg[u+i]=udg[n-u+i]=false;//还原现场g[u][i]='.'; }}
}
void solve()
{cin>>n;for(int i=0;i<n;i++)for(int j=0;j<n;j++)g[i][j]='.';dfs(0);
}

运行结果截图:

在这里插入图片描述
在这里插入图片描述

算法二:DFS按每个元素枚举 时间复杂度 O ( 2 n 2 ) O(2^{n^2}) O(2n2),每个位置都有两种情况,总共有 n 2 n^2 n2 个位置

const int N=25;
int n;
char g[N][N];
bool dg[N],udg[N],col[N],row[N];
int k=1;
void dfs(int x,int y,int s)
{if(y==n)y=0,x++;if(x==n){if(s==n){cout<<n<<"皇后的第"<<k++<<"种方案:"<<endl;for(int i=0;i<n;i++)cout<<g[i]<<endl;cout<<endl;}return;}if(!row[x]&&!col[y]&&!dg[x+y]&&!udg[x-y+n])//选 {g[x][y]='Q';row[x]=col[y]=dg[x+y]=udg[x-y+n]=true;dfs(x,y+1,s+1);row[x]=col[y]=dg[x+y]=udg[x-y+n]=false;g[x][y]='.';}//不选dfs(x,y+1,s); 
}
void solve()
{cin>>n;for(int i=0;i<n;i++)for(int j=0;j<n;j++)g[i][j]='.';dfs(0,0,0);
}

运行结果截图

在这里插入图片描述

在这里插入图片描述

算法三:二进制对空间进行优化

int lowbit(int x){return x&-x;}//最低位1及其后面的0构成的数值
const int N=25;
int n;
vector<string>g;
vector<vector<string>>res;
int cnt=1;
void dfs(int a,int b,int c,int k)
{if(k==n){res.push_back(g);return;}for(int i=~(a|b|c)&((1<<n)-1);i;i-=lowbit(i)){int p=lowbit(i);g[k][log2(p)]='Q';//计算第几位是1,用对数函数log2十分方便dfs((a|p)<<1,(b|p)>>1,c|p,k+1);g[k][log2(p)]='.';}
}
void solve()
{cin>>n;vector<string>board(n,string(n,'.'));g=board;dfs(0,0,0,0);for(int i=0;i<res.size();i++){cout<<n<<"皇后的第"<<cnt++<<"种方案:"<<endl;for(int j=0;j<res[i].size();j++){cout<<res[i][j]<<endl;}cout<<endl;}
}

运行结果截图

在这里插入图片描述

在这里插入图片描述


http://chatgpt.dhexx.cn/article/rDBIZ1L5.shtml

相关文章

八皇后问题(递归回溯算法详解+C代码)

为了理解“递归回溯”的思想&#xff0c;我们不妨先将4位皇后打入冷宫&#xff0c;留下剩下的4位安排进4x4的格子中且不能互相打架&#xff0c;有多少种安排方法呢&#xff1f;现在我们把第一个皇后放在第一个格子&#xff0c;被涂黑的地方是不能放皇后的&#xff1a; 第二行的…

算法设计与分析——八皇后问题的实现——代码分析和讲解

文章目录 题目描述思路分析回顾回溯法的基本框架解题框架应用到本题定义问题的解空间定义约束函数模仿回溯法的框架去解决问题 实现源码分析与总结 题目描述 在88格的棋盘上放置彼此不受攻击的8个皇后。国际象棋的规则&#xff1a;皇后可以攻击与之处在同一行或同一列或同一斜…

八皇后问题算法(C语言实现)

1. 八皇后的由来和问题 八皇后问题&#xff0c;是一个古老而著名的问题&#xff0c;是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯贝瑟尔于1848年提出&#xff1a;在88格的国际象棋上摆放八个皇后&#xff0c;使其不能互相攻击&#xff0c;即任意两个皇后都不能处于同一…

八皇后算法解析

今天研究力扣的一道题死活写不出来对应的算法&#xff0c;没办法自己算法基础太差。于是看了下答案&#xff0c;发现使用什么回溯算法&#xff0c;菜鸟表示平时开发期间写的最复杂的程序就是写了两层for循环&#xff0c;已经很牛逼了有木有&#xff1f;这个回溯算法什么鬼&…

递归算法之八皇后问题

八皇后问题&#xff08;英文&#xff1a;Eight queens&#xff09;&#xff0c;是由国际象棋棋手马克斯贝瑟尔于1848年提出的问题&#xff0c;是回溯算法的典型案例。 问题表述为&#xff1a;在88格的国际象棋上摆放8个皇后&#xff0c;使其不能互相攻击&#xff0c;即任意两个…

八皇后问题4种c语言算法

八皇后问题 1.递归回溯法 B站懒猫老师讲的&#xff08;我在这里学的&#xff09; 八皇后问题的递归回溯算法思路&#xff1a;从第一行开始当某一行皇后位置不与前面所有皇后位置冲突那么记录该行皇后位置并调用递归函数进入下一行&#xff0c;摆放下一个皇后&#xff0c;逐个…

数据结构与算法 — 八皇后问题(回溯算法)

问题描述 在88格的国际象棋上摆放8个皇后&#xff0c;使其不能互相攻击&#xff0c;即任意两个皇后都不能处于同一行、同一列或同一斜线上&#xff0c;问有多少种摆法。 假设上图中红点为一个皇后的位置&#xff0c;那么他的同行&#xff0c;列&#xff0c;斜线上都不能再放置…

数据结构与算法-- 八皇后问题(多种实现方案)

八皇后问题解法一(排列筛选法) 本篇我们承接上一篇中的思想&#xff0c;想到了一个经典的算法题&#xff0c;八皇后问题&#xff1a;题目&#xff1a;在8*8的国际象棋上摆放8个皇后&#xff0c;使得其互相不能攻击&#xff0c;即任意两个换后不能在同一行&#xff0c;同一列&a…

C语言开方问题求助

求助&#xff1a; 使用的是Devcpp进行的编程尝试 在写程序的时候遇到了个问题&#xff0c;运行后结果显示为1#j 后来在朋友的帮助下改正了程序&#xff0c;解决了错误。之后的话&#xff0c;我按照我朋友的改正过的程序自己再重新打了一遍&#xff0c;结果运行后的结果还是显示…

C语言笔记

目录 基础... 3 基本类型数据... 5 定义变量... 6 进制... 6 ASCII&#xff08;阿斯克码&#xff09;... 7 输入输出... 8 printf&#xff08;&#xff09;将变量的内容输出到显示器上... 8 scanf &#xff08;&#xff09;[通过键盘将数据输入到变量中] 9 运算符... …

c语言 大数开方,大数加法之C语言函数法(只有正数版)

由于某些原因&#xff0c;我于今天2017-4-19将我的博文搬到博客园了&#xff0c;以后我就在这里扎根了。 之前想过在博客写文章方便日后复习&#xff0c;但一直未能实现&#xff0c;所以&#xff0c;现在这篇是我个人人生中第一篇博客&#xff0c;所以写博客完全没经验&#xf…

开平方的快速算法(C代码)

目录&#xff1a; 一、牛顿迭代法 二、采用移位、加减法、判断和循环实现开平方 三、效率远高于牛顿迭代法开平方法 1、原理 2、实现代码 四、卡马克快速开平方算法(推荐) 1、C-Free模拟验证卡马克开平方 2、移植到实际的项目 3、卡马克快速开平方的由来 1&#xff0…

windows 区域截屏以及延迟截屏

提起在Windows&#xff0c; 我们都会用到截屏功能&#xff0c;今天论述一下window 10系统自带的截图应用Snipping Tool 打开Snipping Tool 找到任务栏下的放大镜图标&#xff0c;点击 在下方输入snipping&#xff0c;会在左侧找到截图软件Snipping Tool&#xff0c;点击可进入…

小米手机解决此区域不可截屏

小米手机解决此区域不可截屏 无意中暂停视频弹出消息&#xff0c;想试试可不可以截屏竟然可以截屏&#xff0c;但是视频一播放就截屏不了了&#xff0c;录屏也是&#xff0c;直接变黑或者是直接提示弹窗&#xff0c;嘻嘻嘻嘻小米bug还是有好处滴

浏览器网页截屏实用小技巧

浏览器开发者工具中自带的截屏太方便了&#xff01; 打开开发者工具&#xff0c;输入 ctrl shift P 快捷键&#xff0c;输入screenshot&#xff0c;出现了四个选项&#xff0c;分别是&#xff1a; 1.area screenshot - 区域截图 2.full size screenshot - 对浏览器所有内容…

如何利用计算机截屏快捷键,电脑怎么截图 电脑选区域截图怎么截 电脑截图快捷键是什么...

电脑怎么截图 按照操作上从易到难的顺序&#xff0c;给你推荐五种截屏方式 &#xff1a; 第一种&#xff1a;Ctrl PrScrn 使用这个组合键截屏&#xff0c;获得的是整个屏幕的图片; 第二种&#xff1a;Alt PrScrn 这个组合键截屏&#xff0c;获得的结果是 当前窗口的图片; 第三…

iOS 截屏指定区域

转自&#xff1a;链接&#xff1a;https://www.jianshu.com/p/39db0fa66c0e 指定截屏代码实现 全屏截图效果 全屏截图效果 指定区域截屏效果 指定区域截屏效果 这里先上代码&#xff0c;代码后面有相关方法的解释第一种方法代码下载 /**创建一个基于位图的上下文&#xff0…

windows如何截屏

截屏是我们平时工作或记录常用的操作&#xff0c;不过有人不知道怎么用系统截屏&#xff0c;今天&#xff0c;小编带来了系统的几种截屏&#xff0c;让我们来看看吧&#xff01; 一、快捷键截图 1. Win shift S&#xff1a;可以选择截图区域的大小&#xff0c;CtrlV粘贴在w…

Android 任意区域截屏

1、全屏截图 Android其实可以做到任意区域截屏&#xff0c;不过我们先来看看整个屏幕截图代码&#xff0c;相信大家很熟悉&#xff0c;代码如下 View decorView activity.getWindow().getDecorView(); decorView.setDrawingCacheEnabled(true); view.buildDrawingCache(); /…

snipaste 固定位置截屏

原文参考&#xff1a; snipaste怎么固定位置截图&#xff0c;如何统一大小截图 一、电脑点击【snipaste】&#xff0c;或者点击键盘的“F1”。 二、在图片&#xff0c;根据自己的需求&#xff0c;画出截图的位置和大小&#xff0c;比如&#xff1a;本篇是500*296。 三、点击右…