算法设计与分析实验报告c++python实现(生命游戏、带锁的门、三壶谜题、串匹配问题、交替放置的碟子)

一、实验目的

1.加深学生对分治法算法设计方法的基本思想、基本步骤、基本方法的理解与掌握;
2.提高学生利用课堂所学知识解决实际问题的能力;
3.提高学生综合应用所学知识解决实际问题的能力。

二、实验任务

1、 编写一个生命游戏:
规则如下:(或者网上找到更详细的规则)
一个人可以有8个邻居;
一个人若只有一个邻居,在下一代会孤独的死去;
若有2或3个邻居,在下一代依然活着;
若有4个或以上邻居,在下一代会因拥挤而死;
死去的人若有3个邻居,在下一代会复活;
所有的死去或复活都在下一代变化时同时发生。
2、 带锁的门:
在走廊上有n个带锁的门,从1到n依次编号。最初所有的门都是关着的。我们从门前经过n次,每次都从1号门开始。在第i次经过时(i = 1,2,…, n)我们改变i的整数倍号锁的状态;如果门是关的,就打开它;如果门是打开的,就关上它。在最后一次经过后,哪些门是打开的,哪些门是关上的?有多少打开的门?
3、三壶谜题:
有一个充满水的8品脱的水壶和两个空水壶(容积分别是5品脱和3品脱)。通过将水壶完全倒满水和将水壶的水完全倒空这两种方式,在其中的一个水壶中得到4品脱的水。
4、串匹配问题
给定一段文本,在该文本中查找并定位任意给定字符串。
要求:
(1)实现BF算法;(必做)
(2) 实现BF算法的改进算法:KMP算法和BM算法;(选做)
5、交替放置的碟子
我们有数量为2n的一排碟子,n黑n白交替放置:黑,白,黑,白…
现在要把黑碟子都放在右边,白碟子都放在左边,但只允许通过互换相邻碟子的位置来实现。为该谜题写个算法,并确定该算法需要执行的换位次数。

三、实验设备及编程开发工具

实验设备:Win8电脑
开发工具:Microsoft Visual c++ 6.0

四、实验过程设计(算法设计过程)

(1)生命游戏

规则可简化为以下,并使用case比对即可使用程式操作:
1.邻居个数为0,1,4,5,6,7,8时则该细胞下次的状态为死亡。
2.邻居个数为2时,则该细胞下次状态为复活。
3.邻居个数为3时,则该细胞下次状态为稳定代码是不断生成细胞存活的状态图,首先细胞默认都是死的,活细胞需要自己一个一个生成。

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <conio.h>
#include <iostream>
#define ROWLEN 10//二维空间行数; 
#define COLLEN 10//二维空间列数; 
#define DEAD 0//死细胞; 
#define ALIVE 1//活细胞; 
using namespace std;
int cell[ROWLEN][COLLEN];//当前生命细胞的状态;
int celltemp[ROWLEN][COLLEN];//用于判断当前细胞的下一个状态
void initcell() {int row,col;for(row=0; row<ROWLEN; row++) {for(col=0; col<COLLEN; col++) {cell[row][col]=DEAD;}}printf("请先输入一组活细胞的坐标位置,请输入(-1,1)结束\n");while(1) {printf("请输入一个活细胞的坐标位置: ");
//		scanf("%d%d",&row,&col);cin>>row>>col;if(0<=row&&row<ROWLEN&&0<=col&&col<COLLEN) {cell[row][col]=ALIVE;} else if(row==-1||col==-1) {break;} else {printf("输入坐标超过范围。\n");}}}
int LinSum(int row,int col) {int count=0,c,r;for(r=row-1; r<=row+1; r++) {for(c=col-1; c<=col+1; c++) {if(r<0||r>=ROWLEN||c<0||c>=COLLEN) {continue;}if(cell[r][c]==ALIVE) {count++;}}}if(cell[row][col]==ALIVE) {count--;}return count;
}
void OutCell() {int row,col;printf("\n细胞状态\n");
//	这种奇怪的符号在制表符里有哦~
//	printf("┍-");for(col=0; col<COLLEN-1; col++) {
//		printf("━━┳");}
//	printf("━━┓\n") ;cout<<endl;for(row=0; row<ROWLEN; row++) {
//		printf("|");for(col=0; col<COLLEN; col++) {switch(cell[row][col]) {case ALIVE:
//					printf("●|");//活细胞;printf("●");//活细胞;break;case DEAD:
//					printf("○|");//死细胞;printf("○");//死细胞;break;default:;}}printf("\n");if(row<ROWLEN-1) {
//			printf("├");for(col=0; col<COLLEN-1; col++) {//输出一行;
//				printf("━━┼");}
//			printf("━━┫");}}
//	printf("┗");for(col=0; col<COLLEN-1; col++) { //最后一行的横线;
//		printf("━━┻");}
//	printf("━━┛\n");cout<<endl;
}
void cellfun() {int row,col,sum;int count=0;for(row=0; row<ROWLEN; row++) {for(col=0; col<COLLEN; col++) {switch(LinSum(row,col)) {//四周活细胞适量;case 2:celltemp[row][col]=cell[row][col];//保持细胞原样;break;case 3:celltemp[row][col]=ALIVE;//复活;break;default://死了;celltemp[row][col]=DEAD;}}}for(row=0; row<ROWLEN; row++) {for(col=0; col<COLLEN; col++) {cell[row][col]=celltemp[row][col];}}for(row=0; row<ROWLEN; row++) {for(col=0; col<COLLEN; col++) {if(cell[row][col]==ALIVE) {//如果是活细胞;count++;//累计或细胞数量;}}}sum=count;OutCell() ;//显示当前细胞状态;printf("当前状态下,一共有%d个活细胞。\n",sum);
}
int main() {char again;printf("生命游戏!\n") ;initcell();						//初始化OutCell();						//输出初始细胞状态;printf("按任意键开始游戏,进行细胞转换。\n");getch() ;
S1:cellfun();
S2:printf("\n继续生成下一次细胞状态(y/n)?");fflush(stdin);cin>>again;if(again=='y'||again=='Y') {goto S1;} else if(again=='n'||again=='N') {goto S3;} else {printf("输入错误,请重新输入!\n");goto S2;}
S3:printf("游戏结束!\n");return 0;
}

(2)带锁的门

门的状态只有两 种,每经过一次,状态就会发生变化。如果一道门经过奇数次,那么结果状态和原始状态就会不一样,而经过偶数次则不会发生变化。因此问题的关键就是找出那些 经过奇数次的门有多少道。很幸运,那些门的编号正好是整数i的完全平方数即1,4,9,16,…,因此只需要找出这样的数字有多少个即可。
如:假设n = 5
0表示门是关着的,1表示门打开的
一 二 三 四 五
一 1 1 1 1 1
二 1 0 1 0 1
三 1 0 0 0 1
四 1 0 0 1 1
五 1 0 0 0 0
可以发现对角线上的数字就是最后门打开的情况,正好是i的平方数

#include <stdio.h>
#define N 1000
int main()
{
int L[N];
int i,j,k;
int n;
printf("请输入小于1000的整数代表门的总数:");
while(1)
{scanf("%d",&n);if(n<0||n>1000)printf("输入错误,请重新输入");else break;
}
for(i=0;i<n;i++)L[i]=0;
for(j=1;j<=n;j++)
for(k=1;k<=n;k++)
if(k%j==0)
L[k-1]=(L[k-1]+1)%2;
for(i=0;i<n;i++)
{
if(L[i]==1)
printf("第%d号门开着\n",i+1);
}
printf("\n");
return 0; 
}

(3)三壶谜题

可以把每次三个水壶中水的量组成一个状态,比如初始状态为008,对应第一个水壶0品脱水,第二个水壶0品脱水,第三个水壶8品脱水。对题目的状态空间图进行广度优先遍历。当表示状态的数字中出现4时,即求出答案。

1、为了打印出倒水的过程,需要声明一个前置状态保存当前状态由哪个状态转换而来,然后就可以回溯到初始状态,打印出倒水过程。相当于树中的父结点。

2、可以声明一个map表,保存已有的状态,对已有的状态,就不再向下继续遍历,这样可以节省求解时间。

3、因为是广度优先遍历,所以第一次解得的答案所需的倒水的次数最少,解为最优解。

#include <iostream>
#include <vector>
#include <map>
#define MaxFirst 3
#define MaxSecond 5
#define MaxThird 8
using namespace std;class State
{
public:int second;int num[3];State* preState;static map<int,int> mapping;public:State(int first,int second,int third){num[0]=first;num[1]=second;num[2]=third;	}void init(){		mapping[0]=MaxFirst;mapping[1]=MaxSecond;mapping[2]=MaxThird;}bool canPour(int from,int to)//判断是否可以从from水壶中倒水到to水壶中{if(num[from]==0){return false;}if(num[to]==mapping[to]){return false;}else {return true;}}void pour(int from,int to)//倒水过程{if(num[from]+num[to]>mapping[to]){num[from]=num[from]-(mapping[to]-num[to]);num[to]=mapping[to];}else{num[to]=num[to]+num[from];num[from]=0;}}};
map<int,int> State::mapping;int main()
{map<int,int> states;State *start=new State(0,0,8);start->init();State *state=start;State *endState=new State(8,8,8);//只有获得解endState才会改变,赋值全为8为了方便判断是否获得最终解vector<State> action;//保存所有状态对象action.push_back(*start);//把初始状态先加入队列中int n=0;do{for(int i=0;i<3;i++)//双层循环为从i水壶中倒水入j水壶中{for(int j=0;j<3;j++){if(i!=j){if(state->canPour(i,j)){state->pour(i,j);if(states[state->num[0]*100+state->num[1]*10+state->num[2]]==0)//如果该状态不在hash表中,即为第一次出现该状态{states[state->num[0]*100+state->num[1]*10+state->num[2]]++;(state->preState)=new State(action[n]);action.push_back(*state);if(state->num[0]==4||state->num[1]==4||state->num[2]==4)//获得解{endState=state;i=4;break;	}}}}*state=action[n];}			}n++;}while(endState->num[0]==8&&endState->num[1]==8&& n<action.size());cout<<endState->num[0]<<" "<<endState->num[1]<<" "<<endState->num[2]<<endl;state=endState;do{state=state->preState;cout<<state->num[0]<<" "<<state->num[1]<<" "<<state->num[2]<<endl;		}while(state->num[2]!=8);return 0;
}

(4)串匹配问题

BF算法是将所有目标字符串中的子串与需查找的字符串进行比较,成功则返回该子串在目标字符串中的位置,失败则继续比较直至成功或所有子串全部比较,如果都失败,则返回一个成功是不可能出现的值。

在实现时有一个难点:如何获得全部子串。其实事实是并不用获取全部子串,只需要遍历整个目标字符串,分别让以目标字符串中的每个字符为开始位置的子串与需查找字符串对比,一旦对比失败,立即放弃所有以此字符开头的字符串,重新在目标字符串中以下一字符为开始的所有子串中查找需查找字符串。如果对比需查找字符串成功,直接返回该字符位置在目标字符串中的位置。在这里对比失败后需要定位目标字符串中下一字符的位置,这里使用双层循环跳出第二次循环的方法,也可以只用一层循环,使用当前目标字符串位置减去需查找字符串位置再加1。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
/*BF算法--串的匹配 
*/
int BF(char s[],char t[])
{int i=0,j=0;while(i<strlen(s) && j<strlen(t)){if(s[i]==t[j]){i++;j++;}else{i = i-j+1;j = 0;}}if(j>=strlen(t)){return (i-strlen(t));}else{return -1;}
} 
int main()
{char s[]="";char t[]="";cin>>s;cin>>t;int cnt = BF(s,t);printf("%d\n",cnt);return 0;
}

(5)交替放置的碟子

首先把问题转化一下,用1表示黑碟子,0表示白碟子,那么目前的顺序是:

1010…1010

结果要求1都放在右边,0都放在左边。这个题目看起来很眼熟。看关键字:交换相邻的碟子,排好顺序。嗯,就是经常出现在面试中的冒泡排序了。

为便于观察,假设目前有6个碟子:101010。使用冒泡排序,第一次迭代,碟子序列变为:010101,交换3次。在进行第二次迭代之前,观察一下。

现在,不仅第一个碟子就位,最后一个也是了,因此第二次迭代只需要对第2到第5个进行排序,巧合的是,碟子[2->5]仍然是10交替出现,不过比上一次少了两个,这样就简单了,可以得到结论:对于2n个碟子,可以使用n次迭代完成,交换的次数分别是:n+(n-1)+…+2+1,即n(n+1)/2。

#include <stdio.h>
#include <stdlib.h> 
int main()
{int n,num=0;printf("输入碟子的总数量:");scanf("%d",&n);printf("请输入碟子的数量2n,其中黑白碟子各n个:\n");int sum[100];// 将所有碟子存放在一个数组里,设白碟子值为1,黑碟子值为2,//初始排序为:21212121……//换位后排序为 11112222……for(int i=0;i<=(n-2)/2;i++){sum[2*i]=2;sum[2*i+1]=1;}//输出碟子的初始排序 printf("一开始的顺序为:");for(i=0;i<n;i++){printf(sum[i]+" ");if(sum[i]==1){printf("白 ");}else{printf("黑 ");}}printf("\n");//进行排序for(i=0;i<n-1;i++){for(int j=0;j<(n-1-i);j++){if(sum[j+1]<sum[j]){int t=sum[j];sum[j]=sum[j+1];sum[j+1]=t;num++;}}}printf("排序后的顺序为:");for(i=0;i<n;i++){printf(sum[i]+" ");if(sum[i]==1){printf("白 ");}else{printf("黑 ");}}printf("\n一共换位了%d次",num);printf("\n");return 0;
}

五、实验结果及算法复杂度分析
(1)

img

算法复杂度分析
时间复杂度:O(4n^2)
(2)

image-20240404000937003

法复杂度分析
时间复杂度:O(n^2+2n)
(3)

img

算法复杂度分析
时间复杂度:O(n^2)
(4)

img

算法复杂度分析
最坏时间复杂度:O(m*n)
(5)

黑白碟子问题

算法复杂度分析
时间复杂度:O(n(n+1)/2)

实验小结(包括问题和解决方法、心得体会等)

通过本次的实验,对分治算法有了一定的了解,分治就是把一个任务,分为形式和原任务相同,但是规模更小的几个部分任务,分别完成,或只需要选一部分完成,然后再处理完成后的这一个或几部分的结果,实现整个任务的完成。而且本次实验使得我又巩固了一遍c/c++的语言代码,在以后的学习中,还要努力去提高编程能力。

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

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

相关文章

全面学习SpringCloud框架指南

要深入学习Spring Cloud框架,你需要系统地掌握其核心组件和概念,并了解如何在实际项目中应用这些知识。以下是一些关键的学习点和相应的学习内容: 一共分为10个模块包括: 1、微服务架构基础: 理解微服务架构的概念和优势。 学习单体架构向微服务架构演进的过程。 掌握…

计算机网络 Telnet远程访问交换机和Console终端连接交换机

一、实验要求和内容 1、配置交换机进入特权模式密文密码为“abcd两位班内学号”&#xff0c;远程登陆密码为“123456” 2、验证PC0通过远程登陆到交换机上&#xff0c;看是否可以进去特权模式 二、实验步骤 1、将一台还没配置的新交换机&#xff0c;利用console线连接设备的…

【高端电流检测IC储能产品应用方案】耐压28V侧轨的电流检测芯片FP130A 应用于电脑电源,开关电源以及多口快充充电器,户外移动电源,适配器,电池充电器等

电流检测技术常用于高压短路保护、电机控制、DC/DC换流器、系统功耗管理、二次电池的电流管理、蓄电池管理等电流侦测等场景。对于大多数应用而言&#xff0c;都是间接测量电阻两端的跨压差来获取待测电流。 如下面的高端电流检测芯片FP130A&#xff0c;丝印是FC915。电路原理图…

MySQL数据库的详解(1)

DDL&#xff08;数据库操作&#xff09; 查询 查询所有数据库&#xff1a;show databases;当前数据库&#xff1a;select database(); 创建 创建数据库&#xff1a;create database [ if not exists] 数据库名 ; 使用 使用数据库&#xff1a;use 数据库名 ; 删除 删除数…

利用Python实现可视化交互界面:Dash

Dash是一个低代码数据框架&#xff0c;用Python实现可视化交互界面&#xff0c;不用写Javascript&#xff0c;开源&#xff0c;支持回调、HTML组件等功能。 安装 pip install dash使用 # Import packages from dash import Dash, html, dash_table, dcc, callback, Output, …

网络安全JavaSE第六天

7. 数组 7.3.5 数组排序 7.3.5.1 冒泡排序 冒泡排序的思路&#xff1a;相邻两个元素进行比较&#xff0c;如果前面元素比后面元素大就交换位置&#xff0c;每一趟执行完后&#xff0c; 就会得到最大的数。 排序过程分析&#xff1a; package com.openlab; /** * 冒泡排序 */…

pyside6自定义部件库和软件框架的建设记录

一、自定义部件库 原则上尽量做到前后端分离&#xff0c;接口方便&#xff0c;复制简单。 1、单选框部件 # encoding: utf-8 ################################################### # 自定义的单选框 #################################################### 对外…

基于模型预测算法的含储能微网双层能量管理模型

基于模型预测算法的含储能微网双层能量管理模型 文章目录 基于模型预测算法的含储能微网双层能量管理模型一、项目介绍二、源程序下载 一、项目介绍 代码主要做的是一个微网双层优化调度模型&#xff0c;微网聚合单元包括风电、光伏、储能以及超级电容器&#xff0c;在微网的运…

Go语言mac环境搭建详解

Go语言mac环境搭建详解见视频&#xff0c;视频下方也有讲解具体的操作步骤。 Golang Mac电脑环境搭建、开发工具Vscode配置 Go语言mac环境搭建步骤如下&#xff1a; 1、下载安装Golang Go官网下载地址&#xff1a;https://golang.org/dl/ Go官方镜像站&#xff08;推荐&…

Windows下如何确定DLL动态库是32位还是64位

文章目录 Windows下如何确定DLL动态库是32位还是64位使用dumpbin工具可能出现的问题结果输出内容 Windows下如何确定DLL动态库是32位还是64位 使用dumpbin工具 dumpbin.exe通常位于Visual Studio的安装目录下的VC\bin或VC\Tools\MSVC\<version>\bin\Hostx64\x64 比如&am…

海山数据库(He3DB)Redis技术实践:继承开源Redis精髓,强化升级企业级服务

数字化转型中的企业数据的处理速度和效率直接关系到企业的竞争力&#xff0c;Redis作为业界广泛使用的开源键值对存储系统&#xff0c;以其卓越的性能和丰富的数据结构&#xff0c;成为了众多开发者和企业的首选。然而&#xff0c;近期Redis开源社区对Redis协议进行了变更&…

电力综合自动化系统对电力储能技术的影响有哪些?

电力综合自动化系统对电力储能技术的影响主要体现在以下几个方面&#xff1a; 提高能源利用效率&#xff1a;电力综合自动化系统通过优化调度和能量管理&#xff0c;可以实现储能设备的有效利用&#xff0c;提高能源利用效率。在电力系统中&#xff0c;储能设备可以有效地平抑风…

贪心算法:排列算式

题目描述 给出n数字&#xff0c;对于这些数字是否存在一种计算顺序&#xff0c;使得计算过程中数字不会超过3也不会小于0&#xff1f; 输入描述: 首行给出一个正整数t,(1≤t≤1000)代表测试数据组数每组测试数据第一行一个正整数n,(1≤n≤500)第二行包含n个以空格分隔的数字…

Flutter - flutter_gen 资源管理

引言&#xff1a; 在开发 Flutter 应用时&#xff0c;我们经常需要使用各种静态资源&#xff0c;如图片、字体和音频等。如何有效地管理和加载这些资源呢&#xff1f;本篇博客将以图片为例带你解密 Flutter 项目中是如何管理资源地。 assets 加载资源 具体文件名引入 在工程…

STC89C52学习笔记(九)

STC89C52学习笔记&#xff08;九&#xff09; 综述&#xff1a;本文主要介绍了蜂鸣器、蜂鸣器如何使用以及如何利用蜂鸣器播放不同频率声音。 一、蜂鸣器 1.定义和作用 电信号→声音信号&#xff0c;常用来产生按键音和报警音。 2.分类 有源&#xff1a;自带振荡器&#…

机器学习 -- 端到端的机器学习项目

场景 我们将一个端到端的项目&#xff08;一个从开始到结束包含了所有必要步骤和组件的完整项目&#xff09;案例&#xff0c;步骤大概有&#xff1a; 1.观察大局。 2.获得数据。 3.从数据探索和可视化中获得洞见。 4.机器学习算法的数据准备。 5.选择和训练模型。 6.微调模型…

git lfs 大文件管理

简介 git-lfs 是 Git Large File Storage 的缩写&#xff0c;是 Git 的一个扩展&#xff0c;用于处理大文件的版本控制。 它允许你有效地管理和存储大型二进制文件&#xff0c;而不会使 Git 仓库变得过大和不稳定。以下是一些与 git-lfs 相关的常见命令和解释&#xff1a; 常…

unity——Button组件单击双击长按功能

1.实现单击、双击、长按功能 using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; public class ButtonControl_Click_Press_Double : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler {publi…

紫光同创 ----- 集创赛 ---- 点亮LED

目录 一. 安装软件&#xff1a; 1. 按照安装手册一步一步走 2. 等.... 3. 桌面图标 二. 创建工程 1. 双击PDS 2. 点击新建工程 New Project 3. 弹出如下界面 点击 -->> Next 4. 选择工程路径和名称 5. 选择工程类型 6. 剩下的全部next &#xff08;直到…

idea: 没有 new java class

如图&#xff1a; 解决&#xff1a; 右键点击--> Mark Directory as --> Sources Root ok