搜索法求解火柴棍等式问题 基于python
完整代码:https://download.csdn.net/download/pythonyanyan/87430541
任务描述
1.1 作业要求
用火柴棍可以摆成一个数字等式,希望移动一根火柴使得等式成立。
(1)(必做)允许在一个固定的等式库(两位数以内的加减乘法)中选择,从而给出答案。
(2)(必做)允许使用者自己定义,或者输入一个可以求解的等式。如果无解,回答无解。
(3)(必做)给出更多的题目和答案。
(4)(选做)允许移动 2 根火柴棍。
(5)(选做)给出从等式变为新的等式的题目和难度。
1.2 任务完成情况
在本次大作业中,作者完成了必做和选做的全部五个任务,并进行了相关的界面设计。作者认为本次大作业中必做要求 1 与要求 3 在功能上有所重复,因此在应用程序中予以合并。特别的,在第 4 项要求中,我将允许移动的火柴棍根数扩展到了 19 根,超额完成了此项任务哦。
2 问题建模
2.1 模型概述
我们将火柴棍搜索问题等效为一个简单的状态搜索问题,任何一个两位数加减乘法即可表示为一个状态(包括成立等式与不成立等式),起始状态为用户输入的等式或者系统自动生成的等式,目标状态为成立且与原等式不相同的等式。状态转换函数为改变其中任意一个数字或符号。
因此原问题可以化简为:从起始状态到目标状态,找到一条长度等于用户给定步数的路径。然后利用搜索算法进行搜索即可,因此我们需要定义两个状态间的距离,由于每次操作只改变其中一个数字或符号,因此只需要定义数字与数字、符号与符号之间的距离即可。下面几小节详细阐述该定义的过程。
2.2 数字的表示
我们以数码管的形式来表示 0-9 这 10 个数字,如图 1 所示,每个数字最多由 7 根火柴构成,我们将这 7 个位置分别编上 1-7 号。
因此对于 0-9 的每个数字可以由一个 7 位的 0/1 序列来表示:第 i 位为 0 代表该位置上没有火柴;第 i 位为 1 代表该位置上有火柴。在这种表示方式下,数字 0-9 对应的序列如表 1 所示。
图 1:数字的表示
数字 |
对应的 0/1 序列 |
数字 |
对应的 0/1 序列 |
0 |
1110111 |
5 |
1101011 |
1 |
0010010 |
6 |
1101111 |
2 |
1011101 |
7 |
1010010 |
3 |
1011011 |
8 |
1111111 |
4 |
0111010 |
9 |
1111011 |
表 1:数字 0-9 对应的序列
2.3 数字之间的距离
为了表示 0-9 中任意两个数字之间的距离,我们需要用到两个参数,不妨将距离记作(dis1,dis2).
第一个参数 dis1 是目标数字与原数字的火柴数目之差。例如数字 2 由 5 根火柴构成,数字 4 由 4 根火柴构成,从数字 2 变到数字 4 会多出来 1 根火柴,所以距离的第一个参数我们设定为 1。反之,如果火柴数目不够的话,这一参数的取值为负。
第二个参数 dis2 是去掉多余(或补足缺少)的火柴之后还需要移动的最少步数。例如从数字 2 变到数字 4,可以先去除位置 7 的火柴,然后把位置 1 的火柴移到位置 2、位置 5 的火柴移动至位置 6,即需要再移动两次因此距离的第二个参数为 2.
所以从数字 2 到数字 4 的距离可表示为(1,2).
2.4 符号之间的距离
同 2.3,我们可以定义两个符号之间的距离,如表 2 所示(括号中的两个参数表示按照上述方式定义的距离):
表 2:符号之间的距离
3 算法设计和实现
3.1 距离计算算法
3.1.1 算法设计
假设 num1 和 num2 分别为用 7 位 0/1 序列表示的原数字与目标数字,设置三个变量 count1、count2 和 dis1,初始值均为 0。遍历该序列的每一位,如果 num1[i]为 1 且 num2[i]为 0,则 dis1 和 count1 自增 1;如果 num1[i]为 0 且 num2[i]为 1,则 dis1 自减 1、count1 自增 1。最终 dis1 为距离的第一个参数,距离的第二个参数可表示为:
dis2=mincount1,count2
由于符号只有 3 种,因此为了提高搜索效率采用直接列表的方式来查询距离。
3.1.2 算法实现
3.2 答案搜索算法
3.2.1 算法设计
对于 2.1 提出的模型略加修改:用 6 个数字、1 个符号加上未决定的火柴数、已移动的火柴数共 9 个参数来表示状态,初始状态为用户输入或随机生成的 6 个数字和符号,未决定的火柴数、已移动的火柴数初始均为 0。
未决定的火柴数,可以看做是改变完某个数字时多出来(或者缺少的)火柴,已移动火柴数代表从初始状态到现在状态总共移动了多少根。每当状态改变时,未决定的火柴数和已移动的火柴数都要根据数字之间的距离进行更新。
目标状态应满足的条件为:未决定的火柴数等于 0 且以移动的火柴数等于 step(step 为用户开始设定的移动根数)。在搜索上可以采用宽度优先(BFS)的算法,所有状态可以看成是一个深度为 8 的树,第一层为初始状态、第二层为在初始状态下改变第 1 个数字的状态、第三层为在第二层状态下改变第 2 个数字的状态……直到最后一层为改变符号之后的状态,这样我们就可以把所有情况遍历一遍。
事实上,我们并不需要将全部情况都遍历。当我们探索到某个节点时若发现其已移动的火柴数目 >step 时,可以停止对其后续节点的探索,因此这种方法对于移动火柴数较少的情况是非常高效的。
3.2.2 算法实现
3.3 出题算法
3.3.1 算法设计
生成不成立等式:先通过随机数生成一个等式作为初始状态,状态转换函数为改变某个数字或符号,目标状态同样应满足:未决定的火柴数等于 0 且以移动的火柴数等于 step,然后根据 3.2 所述的流程利用广度优先探索目标状态,由于目标状态可能不止一个,当探索到满足目标状态条件时应当及时停止。
生成成立等式:通过随机数生成一个等式即可,该等式求解的难度定义为:diff=2step_min-0.2res_num
其中 step_min 表示解决该等式所需的最小步数,res_num 表示最小步数下,该等式求解方式的个数。该等式的含义为:求解所需步数越多,求解方式越少,该题越难。通常本系统生成的题目难度系数在 6.0 以下。
3.3.2 算法实现
4 界面设计及操作指南
4.1 输入表达式求解
初始界面如图 2,用户首先设置移动火柴的数目,然后将表达式输入到方框内。
图 2:初始界面如果用户的输入不合法,系统会弹出错误提示:
图 3:错误提示在生成题目之后,系统会自动以火柴棍的方式显示在下方区域,用户可以点击“查看答案”按键进行求解,求解完成后会弹出提示框,告诉用户所有答案个数以及搜索用时。关闭提示框后,在界面右下角“所有答案”的列表中,玩家可以查看该题在指定移动根数下的全部答案。
图 4:答案求解
右侧列表为该题的全部答案,选中其中某一项可以在左侧查看答案详情,在左侧以数码管的形式显示出来,方便用户直观地思考:
图 5:查看答案详情如果用户输入的题目无解,系统也会给用户提示:
图 6:无解提示
4.2 系统自动出题
用户首先选择移动的火柴数目,然后点击“系统自动出题(不成立等式)”按钮,即可在下方以火柴棍的形式展示出一道系统出的新题目,与 4.1 一样,用户可以设置求解根数,并点击“查看答案”按钮对该表达式进行求解。
由于大作业要求的第一项设计题库,与自动出题在功能上并无二致区别,为了界面的简洁以及用户的使用体验省去了这个功能。
4.3 从 3 等式变成新的等式
用户可以有两种方式生成等式:一是在输入框中自行输入一个等式,点击“生成题目”即可在下方以火柴棍的形式展示,然后选择移动的火柴数数目,点击“查看答案”进行求解。本算法可以保证新等式与原等式不相同。
第二,用户可点击“系统自动出题(成立等式)”按钮随机生成成立等式,系统会告诉用户完成该题所需的最少移动次数与本题预估难度,如图 7 所示,同样用户可点击“查看答案”对该题进行求解。
图 7:系统自动出题(成立等式)
5 实验总结
为了不与同龄人相比输在起跑线上,我从这个学期开始自学了 Python 语言,深感其实用与便捷。这一次大作业也是我第一次独立地用 Python 语言以及 PyCharm+pyqt 写的大作业。在写核心代码的时候遇到了许多困难,例如字符串、数字、列表之间的转换,还有不熟悉 pyqt 创建界面的方式,通过国庆期间一点点百度加上和同学的探讨,终于将整个大作业的框架完成了。
在搜索算法上,一开始我使用了暴力搜索的方式,即对于每根火柴进行递归搜索,可以想象该算法实际运行起来十分缓慢,经过与同学的探讨交流之后,采用了本文中列举的方法,搜索时长有较大提升,同时支持 3 根及以上火柴棍的搜索。
通过本次大作业,我很好地复习了课堂上学到的状态搜索问题以及 BFS 搜索算法
搜索法求解火柴棍等式问题 基于python相关推荐
- 《啊哈算法》学习三 火柴棍等式
通过求解火柴棍等式来学习枚举算法. 现有m根(m≤24)火柴棍,那么可以拼出多少个不同的形如A+B=C的等式呢?(本题根据NOIP2008提高组第二题改编) 注意: 1.加号与等号各自需要两根火柴棍. ...
- Java、python实现啊哈算法 —— chapter3 火柴棍等式
逻辑书上写的已经很清楚了,但是书上的代码里有一点错误,最大能取到的数字是'11111' 而不是'1111',好了,下面上代码: python:def fun(x): #初始化一个方法用来查看某个搭建某 ...
- 第16周 啊哈算法 火柴棍等式
问题及代码: /*m<=24根火柴棍,求可以构造出多少个满足A+B=C的等式, 其中=和+各需2根火柴棍*/ #include<stdio.h> int fun(int x){int ...
- 算法 3.3——火柴棍等式
现在有n跟火柴棍,希望拼出A+B=C的等式.等式中的A,B,C均是用火柴棍拼出来的整数. 0需要6根火柴,1需要2根火柴,2需要5根火柴,3需要5个火柴,4需要4根火柴,5需要5根火柴,6需要6根火柴 ...
- 火柴棍等式(暴力枚举)
题目描述:给你n个火柴棍,判断能够构成多少个A+B=C(A,B,C为由0~9构成的正整数)形式的等式,其中+与=各由两个火柴棍构成,非零数字的最高位不为零,0 ~ 9的构成如下: 时间限制:1s n& ...
- 啊哈!算法—火柴棍等式
现手中有m(m<=24)个火柴棍,希望拼出A+B=C等式.等式中的A.B.C均为火柴棍拼出来的整数(若该数非0,则最高位不能为0). 注意: 1.加号与等号各自需要2根火柴棍: 2.如果A不等于 ...
- 火柴棍等式(NOIP)
问题描述 给你n根火柴棍,你可以拼出多少个形如"A+B=C"的等式?等式中的A.B.C是用火柴棍拼出的整数(若该数非零,则最高位不能是0).用火柴棍拼数字0-9的拼法如图所示: 注 ...
- 蓝桥云算法题之火柴棒等式——Python满分解答
火柴棒等式 题目描述 图片描述 输入描述 输出描述 输入输出样例 示例 1 输入 输出 样例解释 示例 2 输入 输出 样例解释 解题思路 代码实现 题目描述 给你 n 根火柴棍,你可以拼出多少个形如 ...
- 偏微分方程数值解法python_基于python求解偏微分方程的有限差分法资料
基于python求解偏微分方程的有限差分法资料 Computer Era No. 11 2016 0 引言 在数学中, 偏微分方程是包含多变量和它们的偏 导数在内的微分方程.偏微分方程通常被用来求解 ...
最新文章
- linux什么命令只显示ip,linux ip命令
- 用AI变身16岁女孩,抓住40岁违法警察!20岁男大学生钓鱼执法秀翻美国
- LeetCode Battleships in a Board
- Spark详解(七):SparkContext源码分析以及整体作业提交流程
- python发送邮件及附件
- 九、SpringBoot集成Thymeleaf模板引擎
- Python——如何搭建Python的环境
- 《剑指offer》二进制中1的个数
- hdoj 1013 Digital Roots
- java导出富文本到word_富文本编辑器内容实现word导出下载,请各位大神们指点,感激不尽...
- 平均正确率aps apm apl_海口秀英区“三无小区”垃圾分类有高招 投放正确率达96%以上...
- JAVA远程通信的几种选择(RPC,Webservice,RMI,JMS的区别)
- cocos2dx 3.x(移动修改精灵坐标MoveTo与MoveBy)
- 修改Dreamweaver(DW) cs6代码背景为黑色
- python编程狮_python编程狮app
- 【安全资讯】安卓设备容易受到僵尸网络的DDoS攻击
- 直播背后的视频云大战
- PS怎么把图片处理的更清晰
- JAVA使用HttpURLConnection请求HTTPS网站,不需要证书验证的DEMO教程
- 瑞星2008免费版下载
热门文章
- 让你轻松搞懂0-1背包问题(动态规划 C语言版)
- 处理电子邮件的.NET控件MailBee.NET Objects免费下载及使用说明
- 下列( )不是生产微型计算机的厂商,富士康集团技术类招聘笔试题
- 基于51单片机汽车自动照明灯远近光灯proteus仿真原理图PCB
- 最新浙江安全员B考试单选练习题库
- nyoj1170 最大的数
- 组建个人WEB服务器
- OpenStack 网络总结之:理解GRE隧道的工作流程
- [JWT]Auth0的JWT时间序列化问题
- Linux 文件搜索神器 find 实战详解,建议收藏!