转换视角,提炼共性

  • 有时算法本身乍一看是不一样的,而且很不一样,比较结构特点,看不出来有什么共性
  • 如果我们转换下看问题的视角,是否能够找到共性呢

1 ) 对比分书问题和八皇后问题

  • 这两个问题,其实差异很大,但是两者的与或图却非常类似
  • 这意味着,这两者在算法上是同一类问题,可以使用相同的程序来求解
  • 现在我们来转换一下视角

  • 右边的坐标就是左上位置和右下位置分别对应的喜好和棋子的简化表示
  • 对于书和棋子这两类问题都是往坐标上占一个位置
  • 好,顺着这个思路:

  • 对分书而言

    • C同学挑了2号书,那么C同学不能再挑其他书籍了(即水平的黄线表示)
    • 同时2号书不能被其他同学挑了(即竖直的橙线表示)
    • 所以,这个水平竖直的交叉点代表了这个位置的四个方向不能再次被占用,约等同于皇后的8个方向不能被占用
  • 经过对比,发现它们都可抽象成同一问题,即在限定条件下设置矩阵元素
  • 共同都有的限定条件是: 行列不重复、不遗漏
  • 而在八皇后任务中,又增加了一个限定条件,即每条斜线上只能设置一个元素
  • 当然,这两个问题也有区别:
    • 分书问题中,可以设置元素的位置是矩阵的一个子集,即题面描述中给出的用户与图书之间的喜好关系表
    • 八皇后问题中,所有位置均可以选择,没有限制
      • 如果棋盘上有破洞,或者有些地方放置地雷等,增加了限制,那就另当别论了

2 ) 分书和八皇后问题算法重构

#include <iostream>
using namespace std;
// #define QUEEN // 条件编译:根据条件进行打开操作
#ifdef QUEEN
const int SIZE = 8;
#else
const int SIZE = 5;
#endif// 定义各行当中的位置
struct place_state {// 各行中的位置int Q[SIZE];// 当前行、(i-j)对角线、(i+j)对角线是否安全 对角线在分书问题中用不到bool S[SIZE], L[2*SIZE-1], R[2*SIZE-1];
};
// 方案数
int num;// 判断某一个位置是否合法
bool IsValid(int row, int col) {#ifdef QUEENreturn true; /// 八皇后棋盘上的所有位置均可以放置皇后,所以总是返回 true
#elseint like[5][5] = {  {0, 0, 1, 1, 0},{1, 1, 0, 0, 1},{0, 1, 1, 0, 1},{0, 0, 0, 1, 0},{0,1,0,0,1} };return like[row][col]; /// 分书问题要求皆大欢喜,只有喜欢的书才返回 true, 0 会转为false, 1会转换为true
#endif
}// 是否安全
bool IsSafe(place_state state, int row, int col) {#ifdef QUEENreturn state.S[row] && state.R[col + row] && state.L[col - row + (SIZE - 1)];
#elsereturn state.S[row];
#endif
}// 是否完成
bool IsDone(int col) { return col == SIZE;
}// 输出状态
void OutState(place_state state) {for (int k = 0; k < SIZE; k++) cout << state.Q[k] << ' '; cout << endl;
}// 产生新的状态
place_state GetNewState(place_state state, int row, int col) { state.Q[col] = row;state.S[row] = false;
#ifdef QUEENstate.L[col - row + (SIZE - 1)] = state.R[col + row] = false;
#endifreturn state;
}// 初始化棋盘状态
place_state CreateInitState() {place_state state;for (int i = 0; i < SIZE; i++) {state.Q[i] = -1;state.S[i] = true; }
#ifdef QUEENfor (int i = 0; i < 2*SIZE-1; i++) state.L[i] = state.R[i] = true;
#endifreturn state;
}void Try(int col, place_state state) { // 递归中止条件:所有列均已处理if (IsDone(col)) {num ++;cout << "方案" << num << ": "; OutState(state);return;}for (int row = 0; row < SIZE; row++) { // 1.1 判断当前位置是否合法 针对分书 或者有炸弹的8皇后,目前8皇后不需要if (!IsValid(row, col)) continue;// 1.2 判断当前位置是否可行if (!IsSafe(state, row, col)) continue;// 2. 记录位置,更新状态place_state next_state = GetNewState(state, row, col);// 3. 递归求解下一个位置Try(col+1, next_state);}
}int main() {num = 0;place_state state = CreateInitState();Try(0, state);return 0;
}
  • 经过我们的抽象处理, 两个问题都变成了在限定条件下设置矩阵的元素的问题
  • 再来对比下之前的下楼和跳马,这四个问题也有通用的地方
    • 它们的与或图都很像, 都是递归和一些分叉
    • 都可以继续抽成同一个算法框架

数据结构与算法笔记:抽象思维之转换视角,提炼共性(分书和八皇后问题算法重构)相关推荐

  1. 数据结构源码笔记(C语言):哈希表的相关运算算法

    //实现哈希表的相关运算算法 #include<stdio.h> #include<malloc.h> #include<string.h>#define MaxS ...

  2. 数据结构源码笔记(C语言):二叉平衡树的相关操作算法

    //二叉平衡树的相关运算 #include<stdio.h> #include<malloc.h> #include<string.h>typedef char I ...

  3. 八皇后BFS算法、DFS算法、A*算法代码理解

    代码参考了Python:DFS/BFS/UCS解决八皇后问题_流动的风与雪的博客-CSDN博客 和Python:GBF/A*算法解决八皇后问题_流动的风与雪的博客-CSDN博客 但是我花了两天时间才看 ...

  4. 八皇后回溯算法原理剖析及其JS实现

    八皇后回溯算法(JS实现) 八皇后算法描述如下: 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法! 下面来分析一波,假设此时我 ...

  5. 【Java数据结构与算法】第五章 递归、迷宫回溯和八皇后问题

    第五章 递归 文章目录 第五章 递归 一.递归 1.概念 2.代码实现 3.递归的规则 二.迷宫回溯 1.要求 2.代码实现 三.八皇后问题 1.介绍 2.思路 3.代码实现 一.递归 1.概念 简单 ...

  6. 按照自己的理解用js实现八皇后的算法

    八皇后规则:任意两个棋子都不能处于同一行.同一列或同一斜线上 分析:(下面 将要放的棋子用a表示,已经放下的棋子用b表示) 一.横轴不重复 横轴不重复,也就是说水平方向只能有一个棋子 :所以我们可以采 ...

  7. 八皇后 拉斯维加斯算法

    拉斯维加斯算法的一个显著特征就是它所做的随机性决策有可能导致算法找不到所需的解.因此常用一个bool型函数表示拉斯维加斯算法.找到解就返回true,否则返回false. n后问题典型的有回溯法(n后问 ...

  8. 【练习】2021下半年数据结构刷题笔记和总结 (二) 树、查找-- 不同的排序算法、二叉排序树 平衡二叉树、哈希表查找、线索二叉树、

    记录自己下半年写题目的记录.题目来自书或者网站. 练习(一)的地址: https://blog.csdn.net/qq_41358574/article/details/117098620?ops_r ...

  9. 算法笔记_028:字符串转换成整数(Java)

    1 问题描述 输入一个由数字组成的字符串,请把它转换成整数并输出.例如,输入字符串"123",输出整数123. 请写出一个函数实现该功能,不能使用库函数. 2 解决方案 解答本问题 ...

最新文章

  1. rockmq运维指令_RocketMQ运维监控
  2. 2021年的第一盆冷水:有人说别太把图神经网络当回事儿
  3. vscode使用汇总——常用插件、常用配置、常用快捷键
  4. Facebook开源算法代码库,轻松复现前沿视频理解模型
  5. FFMPEG使用参数详解
  6. rtmp 常用字段含义
  7. java相册_精致小巧的java相册制作方法
  8. Vagrant 快速入门
  9. Activiti6 use spring-boot-starter-web meet requestMappingHandlerMapping error
  10. C++子对象和堆对象
  11. Alpha 冲刺 (6/10)
  12. NASA、西门子和大众都在用的 IoT 协议可遭滥用
  13. python时间序列函数_Python中的时间序列分解函数
  14. 递归解决字符串逆序输出
  15. oracle 切换cdb,CDB与PDB之间的切换方法
  16. T检验三种方法的区分
  17. GDB 用法之查看内存
  18. 安装图形化界面consol/centos-xfce-vnc
  19. 《电子元器件的可靠性》——2.5节威布尔分布及其概率纸的结构和用法
  20. SpannableString字体大小自适应

热门文章

  1. 高等数学学习笔记——第二十九讲——罗尔定理与拉格朗日中值定理
  2. 18uec++多人游戏【服务器为两个角色发枪,并能在线开枪】
  3. OpenCV中使用Eigenfaces人脸识别器识别人脸实战(附Python源码)
  4. 【易购管理系统】导航折叠效果
  5. 20220413安装旧版本的百度网盘的方法
  6. JAVA面试算法小记
  7. CSS单位px、em、rem及它们之间的换算关系
  8. DRAM 内存介绍(一)
  9. 第九届大唐杯国赛获奖名单
  10. 阿里云 ECS 服务器上如何搭建 Hadoop 集群详细步骤图解