八皇后问题

article/2025/9/10 20:06:36

八皇后问题

八皇后问题(英文:Eight queens),是由国际西洋棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。

问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。计算机发明后,有多种计算机语言可以编程解决此问题。

八皇后问题就有有一个8*8的棋盘,每一行都可以放置一个皇后,但是放置的皇后不可以在同一列,这一行和前一行以及后一行的皇后不能出现在同一条对角线上,我们就可以使用穷举法来实现这个问题的编程解决。

穷举法是一种针对于密码的破译方法。这种方法很像数学上的"完全归纳法"并在密码破译方面得到了广泛的应用。简单来说就是将密码进行逐个推算直到找出真正的密码为止。比如一个四位并且全部由数字组成其密码共有10000种组合,也就是说最多我们会尝试9999次才能找到真正的密码。利用这种方法我们可以运用计算机来进行逐个推算,也就是说用我们破解任何一个密码也都只是一个时间问题。

当然如果破译一个有8位而且有可能拥有大小写字母、数字、以及符号的密码用普通的家用电脑可能会用掉几个月甚至更多的时间去计算,其组合方法可能有几千万亿种组合。这样长的时间显然是不能接受的。其解决办法就是运用字典,所谓"字典"就是给密码锁定某个范围,比如英文单词以及生日的数字组合等,所有的英文单词不过10万个左右这样可以大大缩小密码范围,很大程度上缩短了破译时间。

通俗来讲就是一个问题的所有解决方案全部列举出来,然后剔除其中不符合要求的方案,剩下的就是符合要求的,放到八皇后问题中,根据要求剔除即可

#include <stdio.h>
#include <assert.h>int  solution = 0;//多少种解法
void  DrawingQueue(int* arr, int len)
{printf("第%d种解法如下:\n", ++solution);printf("***********************************\n");int count1 = 0;//每行皇后前面的空格int count2 = 0;//后面的空格for (int i = 0; i < 8; i++){count1 = arr[i];while (count1 != 0){printf("X   ");//X表示空格count1--;}printf("M   ");//M表示皇后count2 = 8 - 1 - arr[i];while (count2 != 0){printf("X   ");count2--;}printf("\n");}printf("***********************************\n");
}int GetQueen()
{int count = 0;int arr[8];int x = 0;//arr的下标for (int i = 0; i < 8; i++){for (int j = 0; j < 8; j++){if (j == i || j - i == 1 || j - i == -1){continue;}for (int k = 0; k < 8; k++){if (k == j || k - j == 1 || k - j == -1 ||k == i || k - i == 2 || k - i == -2){continue;}for (int s = 0; s < 8; s++){if (s == k || s - k == 1 || s - k == -1 ||s == j || s - j == 2 || s - j == -2 ||s == i || s - i == 3 || s - i == -3){continue;}for (int m = 0; m < 8; m++){if (m == s || m - s == 1 || m - s == -1 ||m == k || m - k == 2 || m - k == -2 ||m == j || m - j == 3 || m - j == -3 ||m == i || m - i == 4 || m - i == -4){continue;}for (int n = 0; n < 8; n++){if (n == m || n - m == 1 || n - m == -1 ||n == s || n - s == 2 || n - s == -2 ||n == k || n - k == 3 || n - k == -3 ||n == j || n - j == 4 || n - j == -4 ||n == i || n - i == 5 || n - i == -5){continue;}for (int p = 0; p < 8; p++){if (p == n || p - n == 1 || p - n == -1 ||p == m || p - m == 2 || p - m == -2 ||p == s || p - s == 3 || p - s == -3 ||p == k || p - k == 4 || p - k == -4 ||p == j || p - j == 5 || p - j == -5 ||p == i || p - i == 6 || p - i == -6){continue;}for (int q = 0; q < 8; q++){if (q == p || q - p == 1 || q - p == -1 ||q == n || q - n == 2 || q - n == -2 ||q == m || q - m == 3 || q - m == -3 ||q == s || q - s == 4 || q - s == -4 ||q == k || q - k == 5 || q - k == -5 ||q == j || q - j == 6 || q - j == -6 ||q == i || q - i == 7 || q - i == -7){continue;}count++;//printf("i==%d,j==%d,k==%d,s==%d,m==%d,n==%d,p==%d,q==%d\n",//	i, j, k, s, m, n, p, q);arr[x++] = i;arr[x++] = j;arr[x++] = k;arr[x++] = s;arr[x++] = m;arr[x++] = n;arr[x++] = p;arr[x++] = q;DrawingQueue(arr, 8);x = 0;}}}}}}}}return count;
}int main()
{int count = GetQueen();printf("count=%d\n", count);return 0;
}

 这样就可以得到每一种解法的具体分布位置

这就是穷举法的典型示例

硬币问题


在一个陌生的国度,有5种不同的硬币单位:15,23,29,41和67分.寻找所有组成18元8分(即1808分)的可能组合,有多少种可能?
假定对于所有面值的硬币你都有足够的硬币.

这道题目说leetcode上的题目

我们也可以通过穷举法实现

int  GetCoin()
{int count = 0;for (int i = 0; i < 1808/15; i++){for (int j = 0; j < 1808 / 23; j++){for (int k = 0; k < 1808 / 29; k++){for (int m = 0; m < 1808 / 41; m++){for (int n = 0; n < 1808 / 67; n++){if (i * 15 + j * 23 + k * 29 + m * 41 + n * 67 == 1808){count++;}}}}}}return count;
}


还有一道35美分的题目,和这个题目的解决方法是相同的,但是值得注意的是为什么把18元8角换成1808,这个主要是因为double类型的数据在输入时的零的个数会影响最终的结果

所以类似题目我们一般都采用转换为int类型直接使用

其次我们可以看到这个代码的时间复杂度是很高的,所以我们要对他进行优化,可以采用和八皇后问题类似的方法进行优化

int  GetCoin1()//优化版本
{int count = 0;for (int i = 0; i < 1808 / 15; i++){for (int j = 0; j < 1808 / 23; j++){if (i * 15 + j * 23 > 1808){continue;}for (int k = 0; k < 1808 / 29; k++){if (i * 15 + j * 23+k*29 > 1808){continue;}for (int m = 0; m < 1808 / 41; m++){if (i * 15 + j * 23 + k * 29 + m * 41 > 1808){continue;}for (int n = 0; n < 1808 / 67; n++){if (i * 15 + j * 23 + k * 29 + m * 41 + n * 67 == 1808){count++;}}}}}}return count;
}
int main()
{int count = GetCoin1();printf("count=%d\n", count);return 0;
}

这样就一定程度降低了他的时间复杂度,得到了一个相对来说优化效果比较好的实现方式。 


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

相关文章

八皇后问题(适合初学者的写法)C语言

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

八皇后问题,秒懂递归回溯(有图详解|c语言)

目录 &#x1f478;&#x1f3fb;前言 &#x1f478;&#x1f3fb;题目介绍 &#x1f478;&#x1f3fb;引入&#xff1a; &#x1f478;&#x1f3fb;解决思路&#xff1a; &#x1f478;&#x1f3fb;理论存在&#xff0c;实践开始&#xff01; &#x1f478;&#x1f…

利用ngrok实现域名映射局域网ip

前言 相信很多开发者都有这样的需求&#xff0c;需要让外网访问你本地的服务器&#xff0c;方便调试本地代码&#xff0c;或者让别人体验到自己做的应用。那么这时&#xff0c;我们需要做的就是将我们本地的端口映射到一个外网的端口上&#xff0c;也就是内网穿透。常见的解决…

python调用手机摄像头,实现实时调用摄像头,需要你的电脑和手机在同一个局域网内

1、android手机上安装一款APP&#xff1a;IP摄像头&#xff0c;app的图片如上图 2.调用代码如下 import cv2cv2.namedWindow("camera", 1) # 开启ip摄像头 video "http://admin:admin10.0.0.32:8081/" # 此处后的ipv4 地址需要改为app提供的地址 cap c…

02、处于不同局域网下的Socket通信(网络部分理论知识)

目录 一、服务器 1、服务器的种类和功能 2、服务器的操作系统 3、IIs、Apache、Tomcat 4、云服务器 弹性云服务器&#xff08;Elastic Cloud Server&#xff0c;ECS&#xff09; 云服务器安全组 二、OSI七层模型与TCP/IP五层模型 三、外网、内网、公网、私网 内网穿透…

使用wireshark抓取聊天信息(局域网内的udp通信)

文章目录 1&#xff0c;实验目的2&#xff0c;实验操作3&#xff0c;总结4&#xff0c;附件 1&#xff0c;实验目的 1.分析这程序所采用的是udp还是tcp 2.在抓取包中找到窃取到的聊天信息 (英文字符和汉字可能经过了某种编码转换&#xff0c;数据包中不是明文) 3.如果是网络连…

安装黑群晖找不到局域网电脑_黑群晖洗白太复杂?我用蒲公英P5轻松实现

前言: 随着网盘时代的结束,剩下的网盘供应商又开启了垄断方式,所以越来越多的小伙伴开始自己组自己的家庭NAS网络存储服务器。比如笔者的一个好基友就是如此。其实开始笔者是想让他直接一步到位,买群晖或者铁威马的NAS,在放入硬盘就可“一劳永逸”。然而,这个小伙伴看到了…

内网穿透实现局域网内搭建私服务器

使用云服务器实现内网穿透。内网里建立一台老旧win机专门用来挂pt&#xff0c;在上面存储视频和软件&#xff0c;而后映射在外网中&#xff0c;通过手机和电脑随时随地的下载和在线观看win机上的视频和文件。 1、修改ssh的默认端口 在公网中使用常用软件的默认端口会导致自己的…

局域网终结者_p2p终结者怎么安装使用 p2p终结者安装使用方法【介绍】

p2p终结者是一款局域网控制软件&#xff0c;他的主要功能就是控制和限制同一个局域网内其它的上网用户&#xff0c;如限制不让别人上QQ&#xff0c;不让别人开网页和不让别人下载&#xff0c;只要他和你在同一网之内你就可以控制他&#xff0c;并且神奇的是&#xff0c;不需要动…

Kali Linux-MSF远控局域网手机

前言 严正声明&#xff1a;本文仅限于技术讨论与分享&#xff0c;严禁用于非法途径。 本文目的&#xff1a;演示如何借助Kali Linux系统的Metasploit渗透测试框架生成远程控制程序&#xff0c;然后感染局域网内的Android手机&#xff0c;从而实现对目标手机数据的读取、音频的…

超级眼局域网监控软件 员工禁止软件 可以控制时间段

第一步&#xff1a; 下载超级眼局域网监控软件&#xff1a; 将经理端安装在管理者的电脑上&#xff0c;员工端安装在需要被监控者的电脑上。 第二步&#xff1a;在经理端电脑上操作。打开管理端软件&#xff0c;扫描所有的被控电脑。然后选择需要管理的电脑&#xff08;可以全选…

Kali使用Netdiscover探测局域网中存活主机

1、netdiscover介绍 Netdiscover 是一个主动/被动的ARP 侦查工具。使用Netdiscover工具可以在网络上扫描IP地址,检查在线主机或搜索为它们发送的ARP请求。 2、 主动模式:主动模式顾名思义就是主动的探测发现网络内主机,但是这种方式往往会引起网络管理员的注意。 打开Kali终…

如何避免计算机被别人共享,win7如何防止别人偷窥电脑 win7防止别人偷窥电脑操作方法...

我们都知道在win7系统中&#xff0c;可以设定开机密码或者屏保密码来防止我们的电脑被别人使用&#xff0c;不仅win7系统可以设置开机密码或者屏保密码&#xff0c;其他版本的系统也是可以设置的&#xff0c;那么win7如何防止别人偷窥电脑呢?下面为大家介绍win7防止别人偷窥电…

【时间之外】监控你的电脑只需8步

最近某安全厂商很火&#xff0c;很多离职员工都是被这套系统抓出来的。其实原理很简单&#xff0c;本文就用很多人都用过的kali系统&#xff0c;告诉你&#xff0c;想要控制你的电脑有多简单&#xff01; 网上的文章很多&#xff0c;如这篇&#xff0c;Kali攻防&#xff0c;写…

详细介绍别人电脑访问到自己电脑运行的项目

文章目录 让别人远程访问你的代码网站项目或临时演示你的项目给客户的方式详解 引言一、创建一个你想要别人访问的项目二、明确你想要将这个网站或者项目存放的地方 终端分类服务器设备WEB服务器三、部署我们的网页 本地部署流程进入浏览器输入网址访问获取本机的IP地址&#…

监控手机屏幕、监控电脑屏幕方案

一&#xff1a;手机投屏 实时监控多个手机屏幕&#xff08;<3台&#xff09; ApowerMirror软件&#xff0c;终生179&#xff0c;可同时连接3部手机 网络环境&#xff1a;电脑与测试手机需要在同一个WiFi网络环境下。(要求手机型号不同) 软硬件环境&#xff1a;电脑和手机分别…

基于VC++的局域网内主机监控系统设计与实现

局域网内主机监控系统 目录 引言 2 1.1 编写目的 2 1.2 项目背景 2 1.3 课题内容和要求 3 1.4 名词解释 4 参考文献 4需求分析 5 2.1 现有系统概述 5 2.2 对新系统的要求 5 2.3 系统要求 6 2.4 对功能的规定 6 2.5 对性能的规定 6 2.6 运行环境规定 7 2.6.2 软件配置 7系统架…

同一个局域网之内,如何远程控制对方的电脑而且不用对方同意

条件&#xff1a; 1、同一个局域网之内&#xff1b; 2、远程控制对方电脑&#xff1b; 3、不用对方做任何操作&#xff08;QQ远程控制需要对方点击同意才能进行远程&#xff09; 具体操作如下&#xff1a; 一、关闭对方电脑的防火墙 二.允许电脑被对方远程 计算机-属性-远…

详解LinkedList

目录 一、介绍 二、源码分析 1、LinkedList实现的接口 2、LinkedList中的变量 3、LinkedList的构造方法 &#xff08;1&#xff09;无参构造方法 &#xff08;2&#xff09;带集合参数的构造方法 4、LinkedList中的重要方法 &#xff08;1&#xff09;静态内部类Node …

java linkedlist 节点_JAVA学习-LinkedList详解

1.定义 实现List接口与Deque接口双向链表&#xff0c;实现了列表的所有操作&#xff0c;并且允许包括null值的所有元素&#xff0c;对于LinkedList定义我产生了如下疑问&#xff1a; 1.Deque接口是什么&#xff0c;定义了一个怎样的规范? 2.LinkedList是双向链表&#xff0c;其…