算法设计与分析实验报告c++实现(N皇后问题、卫兵布置问题、求解填字游戏问题、图的m着色问题)

一.N皇后问题

基本原理和思路:
从一条路往前走,能进则进,不能进则退回来,换一条路再试。在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。
而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。

代码实现如下:

#include <iostream>
#include <cmath>
using namespace std;
//皇后的个数,方案数目
int n,sum=0;
//记录放置方案
int x[100];//不能这样定义int *x;
//用户递归求取方案
void Queen1(void);
void TraceBack(int);
void PrintMethod(void);
//检查这一皇后放置方案是否满足要求
int Place(int);int main()
{cout << "输入皇后个数:" << endl;cin>>n;Queen1();return 0;
}void Queen1(void)
{TraceBack(0);
}
void TraceBack(int r)
{int i;if(r>=n){PrintMethod();//这个函数的正确性还没有得到验证sum++;}else{for(i=0;i<n;i++){x[r]=i;//在下一行判断当前路是不可行的之后,进入同级的另外的路径if(Place(r))//先试探当前这条路是可行的,则进入下一步循环TraceBack(r+1);}}
}
void PrintMethod(void)
{int i,j;cout<<"第"<<sum<<"个方案\n";for(i=0;i<n;i++){for(j=0;j<n;j++){if(j==x[i])cout<<"1";elsecout<<"0";}cout<<endl;}
}
int Place(int r)
{int i;for(i=0;i<r;i++){if(x[r]==x[i] || abs(r-i)==abs(x[r]-x[i]))//在此处判断皇后走的下一步路是否可行,如果不可行性,return 0;return 0;}return 1;
}

分析:时间复杂度为O(n^n)

二.卫兵步列问题

基本原理和思路:初始令所有的 X [i, j]= 1, i =1,2, …… m , j =1,2, ……n . 算法从 (1,1 )开始直到 (m,n)为止, 搜索树是二叉树,有 m x n 层 . 每个结点对应一个陈列室位置,如果令 X [i, j]= 0 ,取消(i,j ) 位置的哨兵,进入左子树;否则进入右子树。在进入左子树时需要检查房间被监视的情况。 即当取消( i,j )位置的哨兵时,此位置及其上、下、左、右位置是否被监视。

代码实现如下:

#include<iostream>
#include<fstream>
#include<queue>using namespace std;
class Solve;class Node   //Node节点,用来存放搜索树的节点
{friend class Solve;
private:int i;    //当前要放置的新位置 横坐标:i 纵坐标:jint j;int robotNums;    //当前节点已经放置的哨兵数目int beenMonitored;   //当前已经被监视的房间数int** x;    //当前放置哨兵的地方   0表示没有,1表示放置了int** y;    //当前已经被监视的地方   0表示没有,1表示已经监视了int m;      //行int n;      //列public:Node();   //构造函数Node(int m, int n);   //构造函数,m、n是行列数Node(const Node& a);  //这个函数是用于heap的push,push会调用复制构造函数,因此必须自定义一个friend bool operator<(const Node& a, const Node& b);   //重载<,用于优先队列的使用Node& operator=(const Node& a)   //赋值运算符,懒得换位置了{if (x || y){for (int i = 0; i < m + 2; ++i){if (x){delete[] x[i];}if (y){delete[] y[i];}}delete[] x;delete[] y;x = NULL;y = NULL;}i = a.i;j = a.j;robotNums = a.robotNums;beenMonitored = a.beenMonitored;m = a.m;n = a.n;x = new int* [m + 2];y = new int* [m + 2];for (int i = 0; i < m + 2; ++i){x[i] = new int[n + 2];y[i] = new int[n + 2];for (int j = 0; j < n + 2; ++j){x[i][j] = a.x[i][j];y[i][j] = a.y[i][j];}}return *this;}~Node();   //用到了new,因此析构函数要重载,避免内存泄露};class Solve     //解决问题的类
{
private:priority_queue<Node> heap;    //优先队列heapint ans;     //答案所需要的哨兵数目int m;       //行列数int n;int** result;  //答案哨兵的排列顺序public:Solve();Solve(int m, int n);void run(ofstream& fcout);    //进行整个计算+输出void get_min();               //运用分支限界法,寻找最小值void print(ofstream& fcout);  //打印哨兵位置和数目void copy(int** x, int** y);  //将一个二维数组赋值给另一个void change(Node& tmp, int i, int j);   //生成子节点,同时将其添加到heap中
};int main()
{ifstream fcin;fcin.open("input.txt");if (!fcin.is_open()){cout << "文件 input.txt 未能打开" << endl;return -1;}int m, n;fcin >> m >> n;fcin.close();Solve solve(m, n);ofstream fcout;fcout.open("output.txt");if (!fcout.is_open()){cout << "文件 output.txt 未能打开" << endl;return -1;}solve.run(fcout);fcout.close();return 0;
}

分析:复杂度 W(n,m)=O(nm2)。

三. 求解填字游戏问题

  1. 基本原理和思路:从(0,0)开始向右搜索,搜到(3,0)结束
  2. 搜索时记录那些点被用过,下一个点一定是没有被用过的点,使用vis数组标记
  3. 退出条件:搜索到 x == 3时,即此时九个点都已经填了一遍值,输出填入的九个值
  4. 改点是否可以填入,是否合法:使用check函数来检查一下,由于是从左向右开始填起,所以相邻元素只需要考虑上和下两个方向,check函数加上判断边界的条件即可。
  5. 若该点合法,则填入该点,否则继续循环找一个可选点。
  6. 判断边界:即不能超出 3 * 3 的范围,到了最右边要进行换行,否则横坐标直接++即可!具体实现:if(y == 2) dfs(x + 1, 0); else dfs(x, y + 1);
  7. 最后取消标记,回溯上一个点,找下一种选择情况。

代码实现如下:

#include <iostream>using namespace std;int a[3][3], count;
bool vis[10];bool isprime(int n)
{for(int i = 2; i * i <= n; i++){if(n % i == 0) return false;}return true;
}bool check(int x, int y, int k)
{// 上 if(x - 1 >= 0 && !isprime(a[x - 1][y] + k)) return false;// 左 if(y - 1 >= 0 && !isprime(a[x][y - 1] + k)) return false;return true;
}void dfs(int x, int y)
{if(x == 3){for(int i = 0; i < 3; i++){for(int j = 0; j < 3; j++){cout << a[i][j] << " ";}cout << endl;}cout << endl;count ++;return;}for(int i = 1; i <= 10; i++){if(!vis[i] && check(x, y, i)){a[x][y] = i; vis[i] = true;if(y == 2) dfs(x + 1, 0);else dfs(x, y + 1);a[x][y] = 0; vis[i] = false;}}
}int main()
{dfs(0, 0);cout << "Total: " << count << endl;return 0;
}

分析:采用回溯法,即求全排列,时间复杂度O(n!)

四.求解图的m着色问题

基本原理和思路:MaxSum(i,j):从第i行j列到底边的最大数字之和
从最后一行开始递推,MaxSum(n,j)=D(n,j)//n行j列,MaxSum(n-1,j) = D(n-1,j) + max( MaxSum(n,j) , MaxSum(n,j+1) )
然后为了减少空间,不需要用二维数组来存储MaxSum(n,j)的值,只需要求MaxSum(n,j)的时候存储下一行MaxSum(n+1,j)的值就可以,然后计算完第n行的MaxSum之后再覆盖原来的第n+1行的MaxSum的值。

代码实现如下:

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>using namespace std;const int N = 5;//图的顶点数
const int M = 3;//色彩数
class Color
{friend int mColoring(int, int, int **);
private:bool Ok(int k);void Backtrack(int t);int n,      //图的顶点数m,      //可用的颜色数**a,    //图的邻接矩阵*x;     //当前解long sum;   //当前已找到的可m着色方案数
};
int mColoring(int n,int m,int **a);
int main()
{int **a = new int *[N+1];for(int i=1; i<=N; i++){a[i] = new int[N+1];}cout<<"请输入图G的邻接矩阵:"<<endl;for(int i=1; i<=N; i++){for(int j=1; j<=N; j++){cin>>a[i][j];}cout<<endl;}cout<<"图G的着色方案如下:"<<endl;cout<<"当m="<<M<<"时,图G的可行着色方案数目为:"<<mColoring(N,M,a)<<endl;for(int i=1; i<=N; i++){delete[] a[i];}delete []a;
}void Color::Backtrack(int t)
{if (t>n){sum++;for (int i=1; i<=n; i++)cout << x[i] << " ";cout << endl;}else{for (int i=1; i<=m; i++){x[t]=i;if (Ok(t)) Backtrack(t+1);x[t]=0;}}
}bool Color::Ok(int k)// 检查颜色可用性
{for (int j=1; j<=n; j++){if ((a[k][j]==1)&&(x[j]==x[k])) //相邻且颜色相同{return false;}}return true;
}int mColoring(int n,int m,int **a)
{Color X;//初始化XX.n = n;X.m = m;X.a = a;X.sum = 0;int *p = new int[n+1];for(int i=0; i<=n; i++){p[i] = 0;}X.x = p;X.Backtrack(1);delete []p;return X.sum;
}

分析:时间复杂度是 O ( m ∗ n 2 ) O(m*n^2) O(mn2)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/809673.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第10天:基础入门-HTTP数据包Postman构造请求方法请求头修改状态码判断

第十天 一、HTTP/S 数据包请求与返回 数据-方法&头部&状态码 常规请求-Get——>访问网页获取资源用户登录-Post——>提交数据进行验证 head&#xff1a;与服务器索与 get 请求 一致的相应&#xff0c;响应体不会返回&#xff0c;获取包含在小消息头中的原信息&…

Spring Web MVC的入门学习(二)

本篇接着Spring Web MVC的入门学习&#xff08;一&#xff09;-CSDN博客来继续学习Spring MVC。 一、从请求中获取Header 1、传统获取 header 获取Header也是从 HttpServletRequest 中获取。 代码&#xff1a; import jakarta.servlet.http.HttpServletRequest; import jakar…

vue3+vite+typescript+pinia+element_plus构建web项目

1.vite搭建 yarn create vite 可能会提示node版本不支持&#xff0c;需要根据提示升级或降级node版本 使用nvm下载对应版本 nvm download 18.x.xnvm use 18.x.x// 需要安装yarn npm install -g yarn// 重新执行 yarn create vite 过程中会提供选择&#xff0c;分别选择vue、…

MySQL 实例student表综合查询

目录 例题&#xff1a; 1、查询student表的所有记录 2、查询student表的第2条到4条记录 3、从student表查询所有学生的学号&#xff08;id&#xff09;、姓名&#xff08;name&#xff09;和院系&#xff08;department&#xff09;的信息 4、从student表中查询计算机系和英…

逆向案例二十一——遇到混淆怎么办

开始新的板块尝试&#xff0c;混淆了怎么办 网址&#xff1a;极简壁纸_海量电脑桌面壁纸美图_4K超高清_最潮壁纸网站 抓包抓到&#xff0c;好久没做解密了&#xff0c;奥里给干他&#xff01;&#xff1a; 搜索关键字&#xff0c;打上断点&#xff0c;点击第二页。 _0x10a345…

关于光模块SFP-10G-SR、SFP-10G-LRM和SFP-10G-LR的对比分析

万兆光模块是万兆网络搭建领域中的重要组成部分&#xff0c;是传输万兆速率必要组件。随着网络速率和容量需求的增加&#xff0c;目前万兆光模块的应用量非常大。而在万兆光模块中&#xff0c;短距离光模块的出货量居首&#xff0c;本文将详细介绍3款短距离万兆光模块SFP-10G-S…

PyCharm Pro 2024:卓越的Python编辑开发工具,适用于Mac与Windows平台

PyCharm Pro 2024是一款专为Python开发者设计的强大编辑开发工具&#xff0c;无论是Mac还是Windows用户&#xff0c;都能从中受益良多。该软件凭借其出色的性能、丰富的功能和卓越的用户体验&#xff0c;成为Python编程界的翘楚。 作为一款高效的Python编辑器&#xff0c;PyCh…

什么是MOV视频格式?如何把MP4视频转MOV视频格式?

一&#xff0c;前言 当然可以&#xff0c;MP4视频可以转换为MOV格式。这两种格式都是常见的视频文件格式&#xff0c;它们都可以用于存储和播放视频内容。虽然它们的编码方式和特性有所不同&#xff0c;但使用合适的视频转换工具可以轻松地将MP4视频转换为MOV格式。 二&#…

React-样式使用

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;React篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来React篇专栏内容:React-样式使用 目录 1、行内样式 2、使用className属性 3、css module模块化 4、styled-c…

sidusv指标,fpmarkets澳福愿称之为最强辅助指标

做投资的最怕的就是犹豫不定&#xff0c;抓不住交易的机会&#xff0c;最后又后悔不及。现在不用怕了&#xff0c;fpmarkets澳福今天分享愿称之为最强辅助指标——sidusv指标。可以帮助投资者轻松把握交易时机。 sidusv指标通过箭头指示进入点;红色的是卖出位置&#xff0c;绿色…

linux学习:结构体、联合体、枚举

目录 结构体 例子 大小 联合体 例子 大小 枚举 例子 大小 结构体 结构体就是我们自己发明的数据类型&#xff0c;因此使用结构体至少包含两个步骤&#xff1a; 第一&#xff0c;创建一个自定义的结构体类型。 第二&#xff0c;用这个自己搞出来的类型定义结构体变量 …

如何激怒一位Python爱好者?

写代码不那么pythonic风格的&#xff0c;多多少少都会让人有点难受。 什么是pythonic呢&#xff1f;简而言之&#xff0c;这是一种写代码时遵守的规范&#xff0c;主打简洁、清晰、可读性高&#xff0c;符合PEP 8&#xff08;Python代码样式指南&#xff09;约定的模式。 Pyt…

基于SSM+Jsp+Mysql的宜佰丰超市进销存管理系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

Python实现对一个IP地址和端口号列表进行nmap扫描

一.功能目的 使用python实现对一个IP地址和端口号列表进行nmap扫描 二.功能调研 根据查找得知我们需要用到python的subprocess库 1.代码示例 以下是搜到的简单的subprocess库代码 import subprocess result subprocess.run([ls, -l], capture_outputTrue, textTrue) …

机器视觉系统-什么是光通量

光通量(uminous flux)指人眼所能感觉到的辐射功率&#xff0c;它等于单位时间内某一波段的辐射能量和该波段的相对视见率的乘 积。由于人眼&#xff08;传感器】对不问波长光的相对视见率不同&#xff0c;所以不同波长光的辐射功率相等时&#xff0c;其光通量并不相等。 光通量…

动态规划专练( 343.整数拆分)

343.整数拆分 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。示例 2: 输入: n 10 输出: 36 …

【目标检测】计算YOLOv5/7/8/9的TP, FP, FN, Recall和Precision

1. 设定IoU和Conf阈值 2. 保存推理结果的txt文件 3. 计算TP, FP, FN import osclasses {0: "class 1",1: "class 2"}def iou(box1, box2):box1_x1 box1[0] - box1[2] / 2box1_y1 box1[1] - box1[3] / 2box1_x2 box1[0] box1[2] / 2box1_y2 box1[1…

从零学算法274

274.H 指数 给你一个整数数组 citations &#xff0c;其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。 根据维基百科上 h 指数的定义&#xff1a;h 代表“高引用次数” &#xff0c;一名科研人员的 h 指数 是指他&#xff08;她&#x…

Web程序设计-实验01 HTML与CSS基础

【实验主题】 影视详情页设计 【实验任务】 1、浏览并分析多个影视详情页面&#xff08;详见参考资源&#xff0c;建议自行搜索更多影视网站&#xff09;的主要元素构成和版面设计&#xff0c;借鉴并构思预期效果。 2、新建 index.html文件&#xff0c;合理运用HTML标记编写…

计算机网络——MAC地址和IP地址

目录 前言 引入 MAC地址与IP地址 IP地址和MAC地址是什么&#xff1f;如何起作用的&#xff1f; MAC地址如何表示与确定网卡在网络中的确定位置&#xff1f; DHCP协议自动帮我们配置 操作系统是如何知道对方的MAC地址的&#xff1f; 前言 本博客是博主用于复习计算机网络…