数据结构与算法笔记:抽象思维之对比算法,发现共性(下楼梯台阶和象棋跳马问题算法重构)
关于抽象思维
- 我们需要快速应对世界的复杂多变性,我们就需要有抽象思维
- 抽象思维可以帮助我们提取共性,应对变化
- 抽象思维是我们认识和表达复杂世界的关键
- 抽象思维可以帮助我们分析藏在复杂现象背后的本质和规律
对比算法,发现共性
1 ) 对比下楼问题和跳马问题
- 两个问题的具体分析在前面的文章中已经完成,我们来对比一下两者
- 两者结构很像,都用递归枚举算法, 下楼问题有三个分叉,跳马问题有四个分叉
- 两者与或图基本相同,在算法上是同一类问题,可以使用基本相同的程序来求解
- 两个不同场景下的问题是具有同一性质,但是它们并不能用同一个程序来做,因为它们之间是有差异的
- 两个问题的差异
- 是否达到目标不一致:对下楼而言,高度是否为0;跳马问题,位置坐标是否等于(8,4)
- 新位置的计算:对下楼而言,高度只需要减下来;跳马问题,需要根据规则计算落点坐标
- 判断是否合法:对下楼而言,剩余高度大于等于0;跳马问题,要保证在棋盘之上
2 ) 下楼问题算法重构
#include <iostream>
using namespace std;int h;
int num;
struct position { int x; };
position dxy[] = {{1}, {2}, {3}};
position start_pos = {0}, goal_pos = {h};
position path[100];/* --------------------- 辅助函数 开始 ------------------------ */
bool IsEq(position pos1, position pos2) { return (pos1.x == pos2.x);
}
bool IsDone(position pos) {return IsEq(pos, goal_pos);
}bool IsValid(position pos) {return (pos.x >=0) && (pos.x <= h);
}position GetNewPos(position pos, int k) {position next_pos = {pos.x + dxy[k].x};return next_pos;
}
void LogStep(int step, position pos) {path[step] = pos;
}void OutStep(position pos) { cout << pos.x << ' ';
}void OutAll(int step) {for (int i=0; i<step; i++) {OutStep(path[i]);}cout << endl;
}
/* --------------------- 辅助函数 结束 ------------------------ */// 递归函数
void Jump(position pos, int step) {// 是否达到目标if(IsDone(pos)) {num++; // 方案数+1cout << "当前位置" << num << ": ";OutAll(step); // 输出方案return;}// 遍历N种方案for (int k = 0; k < sizeof(dxy) / sizeof(dxy[0]); k++) {position next_pos = GetNewPos(pos, k);if(!IsValid(next_pos)) {continue; // nex_pos是否可行?}LogStep(step, next_pos); // 记录方案Jump(next_pos, step + 1); // 走下一步}
}// main函数
int main() {// 要求用户输入来更新最终位置cout << "请输入楼梯台阶数:"; cin >> h;position h_num = {h};goal_pos = h_num;num = 0; // 初始方案数置0Jump(start_pos, 0); // 走第一步cout << "总方案数: " << num << endl;return 0;
}
- 这个下楼问题算法重构是逆向思维转化为上楼问题,都是状态的转变
- 当然稍微修改下算法就可以变成下楼问题了,两者方案都是一样的解决方案
- 之前的算法是输出步骤,现在的算法是输出位置
3 ) 跳马问题算法重构
#include <iostream>
using namespace std;struct position { int x, y; };
position dxy[] = {{1,2}, {2,1}, {2, -1}, {1, -2}};
position start_pos = {0, 0}, goal_pos = {8, 4};
position path[100];
int num;/* --------------------- 辅助函数 开始 ------------------------ */
bool IsEq(position pos1, position pos2) {return (pos1.x == pos2.x) && (pos1.y == pos2.y);
}bool IsDone(position pos) {return IsEq(pos, goal_pos);
}bool IsValid(position pos) {return (pos.x >= 0) && (pos.x <= 8) && (pos.y >= 0) && (pos.y <= 4);
}position GetNewPos(position pos, int k) {position next_pos = {pos.x + dxy[k].x, pos.y + dxy[k].y}; return next_pos;
}
void LogStep(int step, position pos) {path[step] = pos;
}void OutStep(position pos) {cout << "(" << pos.x << ", "<< pos.y << ") ";
}
void OutAll(int step) {for (int i=0; i<step; i++) OutStep(path[i]);cout << endl;
}
/* --------------------- 辅助函数 结束 ------------------------ */void Jump(position pos, int step) {// 是否达到目标if(IsDone(pos)) {num++; // 方案数+1cout << "当前位置" << num << ": ";OutAll(step); // 输出方案return;}// 遍历N种方案for (int k = 0; k < sizeof(dxy) / sizeof(dxy[0]); k++) {position next_pos = GetNewPos(pos, k);if(!IsValid(next_pos)) {continue; // nex_pos是否可行?}LogStep(step, next_pos); // 记录方案Jump(next_pos, step + 1); // 走下一步}
}int main() {num = 0; // 初始方案数置0 Jump(start_pos, 0); // 走第一步cout << "总方案数:" << num << endl;return 0;
}
- 从两个问题的算法重构可以看出:
- 通过辅助函数把两个问题的共同特点找回来了,同时把差异的地方隔离开来
- 递归程序完全相同,main函数也趋近一致
- 不管是下马,跳楼,还是是类似的问题,只要稍微修改下,即可成为一个solid的解决方案
- 所以算法重构有很多的好处
4 ) 下楼和跳马问题通用算法框架
void Jump(position pos, int step) {// 是否达到目标if(IsDone(pos)) {num++; // 方案数+1cout << "当前位置" << num << ": ";OutAll(step); // 输出方案return;}// 遍历N种方案for (int k = 0; k < sizeof(dxy) / sizeof(dxy[0]); k++) {position next_pos = GetNewPos(pos, k);if(!IsValid(next_pos)) {continue; // nex_pos是否可行?}LogStep(step, next_pos); // 记录方案Jump(next_pos, step + 1); // 走下一步}
}int main() {num = 0; // 初始方案数置0 Jump(start_pos, 0); // 走第一步 return 0;
}
- 总结一下,这类算法框架的三个关键点:
- 判断结束状态
- 产生新的状态
- 判断是否合法
数据结构与算法笔记:抽象思维之对比算法,发现共性(下楼梯台阶和象棋跳马问题算法重构)相关推荐
- 推荐系统中常用算法 以及优点缺点对比
推荐系统中常用算法 以及优点缺点对比 2014/09/20 [Martin导读]随着互联网特别是社会化网络的快速发展,我们正处于信息过载的时代.用户面对过量的信息很难找到自己真正感兴趣的内容,而内容提 ...
- 《算法笔记》2.3小节——C/C++快速入门-选择结构
<算法笔记>2.3小节--C/C++快速入门->选择结构 Contest100000567 - <算法笔记>2.3小节--C/C++快速入门->选择结构 Conte ...
- 数据结构与算法笔记:抽象思维之转换视角,提炼共性(分书和八皇后问题算法重构)
转换视角,提炼共性 有时算法本身乍一看是不一样的,而且很不一样,比较结构特点,看不出来有什么共性 如果我们转换下看问题的视角,是否能够找到共性呢 1 ) 对比分书问题和八皇后问题 这两个问题,其实差异 ...
- 明翰数据结构与算法笔记V0.8(持续更新)
文章目录 前言 数据结构 `线性表` `数组` `链表` `栈与队列` [串/字符串] 树 并查集 `二叉树` [二叉排序树/二叉搜索树] `红黑树` 红黑树操作 霍夫曼树 `堆` [大/小]根堆 可 ...
- 算法笔记(三)特殊数据结构——哈希表、有序表、并查集、KMP、Manacher、单调栈、位图、大数据类题
layout: post title: 算法笔记(三)特殊数据结构--哈希表.有序表.并查集.KMP.Manacher.单调栈.位图.大数据类题 description: 算法笔记(三)特殊数据结构- ...
- 数据结构与算法笔记 - 绪论
数据结构与算法笔记 - 绪论 1. 什么是计算 2. 评判DSA优劣的参照(直尺) 3. 度量DSA性能的尺度(刻度) 4. DSA的性能度量的方法 5. DSA性能的设计及其优化 x1. 理论模型与 ...
- 数据结构源码笔记(C语言):置换-选择算法
//实现置换-选择算法#include<stdio.h> #include<malloc.h> #include<string.h> #include<std ...
- 数据结构源码笔记(C语言):哈希表的相关运算算法
//实现哈希表的相关运算算法 #include<stdio.h> #include<malloc.h> #include<string.h>#define MaxS ...
- 数据结构源码笔记(C语言):二叉平衡树的相关操作算法
//二叉平衡树的相关运算 #include<stdio.h> #include<malloc.h> #include<string.h>typedef char I ...
最新文章
- php多文件上传类源码,PHP单文件上传类或多文件上传类源码
- ZedGraph曲线图实现X轴与Y轴可拖动,并且对应曲线也一起移动
- 20189211 《网络攻防》第五周作业
- Swift-binary search tree
- Effective Java之静态工厂代替构造器(一)
- Springboot配置不当
- WindowsMobile应该如何发展?(未完待续)
- object转date类型_js-最常用的类型判断
- 创新创业技术路线怎么写_怎么创业起步 如何写创业计划?
- 2021年C++项目中的十大Bug:乍一看都正确的代码,实则暗藏玄机
- 2021芜湖高考成绩查询,2021芜湖市地区高考成绩排名查询,芜湖市高考各高中成绩喜报榜单...
- iOS 使用脚本自动化复制target
- ElasticSearch全文搜索引擎之Linux版安装教程
- Python好酷|allpairspy一款高效的正交实验法生成用例工具
- 批量给excel表中的每行添加表头
- 八类网线测试仪之深入探讨-AEM
- 如何把PPT连背景一起复制?
- Python问题:UnboundLocalError: local variable 'xxx' referenced before assignment
- hp1015驱动64位_在win10/win7 64位系统上安装 hp laserjet 1015对应的打印机驱动
- 规范化、标准化、归一化、正则化
热门文章
- 计算机模拟地球爆炸,模拟地球爆炸
- md 文件使用html阅读,使用markdow-it渲染md文件为html页面
- JavaFX调用虚拟键盘
- mac 命令行查看DNS
- python函数由什么组成_python的函数
- matlab pdepe函数边界,科学网-使用MATLAB中pdepe函数求解一维偏微分方程-邓浩鑫的博文...
- win10看不到家庭组计算机,win10专业版没有家庭组怎么办?一招帮你解决问题
- 计算机的存储器有哪2类,存储器有哪两种
- 快速搭建微信小程序第三方平台基础教程(一)第三方平台是做什么的
- 在UC浏览器投放广告的优势、效果!