backtrack回溯算法
转自台湾师范大学acm课程
Enumerate all n-tuples
列舉重複排列。這裡示範:列舉出「數字 1 到 10 選擇五次」全部可能的情形。
製作一個陣列,用來存放一組可能的排列(數據)。
int solution[5];
例如 solution[0] = 4 表示第一個抓到的數字是 4 , solution[4] = 9 表示第五個抓到的數字是 9 。陣列中不同的格子,就是 solution vector 當中不同的維度。
遞迴程式碼設計成這樣:
int solution[5]; // 用來存放一組可能的數據void print_solution() // 印出一組可能的數據
{for (int i=0; i<5; i++)cout << i << ' ';cout << endl;
}void backtrack(int n) // n 為現在正在列舉的維度
{// it's a solutionif (n == 5){print_solution();return;}// 逐步列舉數字1到10,並且各自遞迴下去,列舉之後的維度solution[n] = 1;backtrack(n+1);solution[n] = 2;backtrack(n+1);......solution[n] = 10;backtrack(n+1);
}int main()
{backtrack(0);
}
輸出結果會照字典順序排列。附送一張簡圖:
注解: 其实就是利用递归来打印出整个字典顺序。注意递归函数中的顺序和递归停止条件。
Permutation
permutation 是「排列」的意思,便是數學課本中「排列組合」的排列。但是這裡並不是要計算排列有多少種,而是實際列舉出所有的排列:
現在有一個集合,裡面有 1 到 n 的數字,列出所有數字的排列,同樣的排列不能重複列出來。例如 {1,2,3} 所有的排列就是 {1,2,3} 、 {1,3,2} 、 {2,1,3} 、 {2,3,1} 、 {3,1,2} 、 {3,2,1} 。
permutation 的問題可以使用 backtracking 的技術來解決!
依序窮舉每個位置,針對每個位置,試著填入各種數字
一般來說, permutation 的程式碼都會長成這樣的格式:
int solution[MAX]; // 用來存放一組可能的答案
bool used[MAX]; // 紀錄數字是否使用過,用過為 truevoid permutation(int k, int n)
{if (k == n) // it's a solution{for (int i=0; i<n; i++)cout << solution[i] << " ";cout << endl;}else{for (int i=0; i<n; i++) // 試著將第 k 格填入各種數字if (!used[i]){used[i] = true; // 紀錄用過的數字solution[k] = i; // 將第 k 格填入數字 kpermutation(k+1, n); // iterate next positionused[i] = false; // 回收用完的數字}}
}int main()
{for (int i=0; i < MAX; i++) // initializationused[i] = false;permutation(0, 10); // 印出0~9,一共10個數字的所有排列
}
permutation 的問題都可以使用這段程式碼來解決。而且這支程式,是以字典順序來列舉出所有排列。所以它真的很有用,不妨參考看看。
依序窮舉每個數字,針對每個數字,試著填入各個位置
另外還有一種作法是生做這個樣子的:
int solution[MAX]; // 用來存放一組可能的答案
bool filled[MAX]; // 紀錄各個位置是否填過數字,填過為 truevoid permutation(int v, int n)
{if (v == n) // it's a solution{for (int i=0; i<n; i++)cout << solution[i] << " ";cout << endl;}else{for (int i=0; i<n; i++) // 試著將數字 v 填入各個位置if (!filled[i]){filled[i] = true; // 紀錄填過的位置solution[i] = v; // 將數字 v 填入第 i 格permutation(v+1, n); // iterate next positionfilled[i] = false; // 回收位置}}
}int main()
{for (int i=0; i<MAX; i++) // initializationfilled[i] = false;permutation(0, 10); // 印出0~9,一共10個數字的所有排列
}
這也是一個不錯的方法,列出來提供大家參考。多接觸各式各樣的方法,能激發一些創意呢!
為了講解方便,以下的文章以一開始提到的方法當作基準。
字串排列
有個常見的問題是:列出字串 abc 的所有排列,要依照字典順序列出。其實這就跟剛才介紹的東西大同小異,只要稍加修改程式碼即可。
char s[3] = {'a', 'b', 'c'}; // 字串,需要先由小到大排序過
char solution[3]; // 用來存放一組可能的答案
bool used[3]; // 紀錄該字母是否使用過,用過為 truevoid permutation(int k, int n)
{if (k == n) // it's a solution{for (int i=0; i<n; i++)cout << solution[i];cout << endl;}else{// 針對solution[i]這個位置,列舉所有字母,並各自遞迴for (int i=0; i<n; i++)if (!used[i]){used[i] = true;solution[k] = s[i]; // 填入字母permutation(k+1, n);used[i] = false;}}
}
backtrack回溯算法相关推荐
- c语言backtrack算法6,一个关于数组回溯算法(backtrack)的通用模式
今天在LeetCode看到一篇非常有价值的讨论,列举了一系列列数组的回溯算法的通用模式,自己动手一个个完成后,感觉对理解回溯算法的原理有很大帮助. 其实回溯就是按顺序的一种穷举,但是它会设定停止条件和 ...
- 回溯算法——算法总结(四)
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法.回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试.用回溯算法解决这个问题的一般步骤为: 1.定义一个解空间.它包括问题 ...
- 算法分析结课总结--回溯算法
以下是回溯算法的经典框架结构: 1 //t:递归的深度,也就是对象的层数.因此每次的回溯遍历都以深度为参数. 2 void backtrack (int t) 3 { 4 if(t>n) //n ...
- 回溯java算法_聊聊算法——回溯算法
"递归只应天上有,迭代还须在人间",从这句话我们可以看出递归的精妙,确实厉害,递归是将问题规模逐渐减小, 然后再反推回去,但本质上是从最小的规模开始,直到目标值,思想就是数学归纳法 ...
- 回溯法遵循深度优先吗_闲来刷下「回溯算法」
定义 ❝ 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就"回溯"返回,尝试别的路径.回溯法是一种选优搜索法,按选优条件向 ...
- 一篇带你搞透回溯算法
回溯算法应用场合 回溯算法和递归算法一般同时出现,一般递归算法的下面就是回溯的逻辑. 一般说递归函数,其实就是回溯函数.回溯一般不会单独出现. 回溯法其实是一个纯暴力的搜索算法.有些问题用for循环搜 ...
- 五大常用经典算法—回溯算法
原文作者:labuladong 原文地址:回溯算法套路详解 读完本文,你可以去力扣拿下如下题目: 46.全排列 51.N皇后 解决一个回溯问题,实际上就是一个决策树的遍历过程.你只需要思考 3 个问题 ...
- 回溯算法团灭子集、排列、组合问题
回溯算法团灭子集.排列.组合问题 一.子集 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = [1,2,3] ...
- 回溯算法详解之全排列、N皇后问题
回溯算法详解 回溯算法框架.解决一个回溯问题,实际上就是一个决策树的遍历过程.你只需要思考 3 个问题: 1.路径:也就是已经做出的选择. 2.选择列表:也就是你当前可以做的选择. 3.结束条件:也就 ...
最新文章
- Android不使用支持库请求运行时权限
- 提高语音识别成功率的解决方案思路一
- Win2003下Exchange2003部署图解之二
- linux 释放进程res_linux内存查看及释放
- 原子性 atomic 类用法
- 下标索引必须为正整数类型或逻辑类型_python量化基础 | 变量和简单的数据类型,零基础都可以看懂...
- nodejs爬虫基础(二)
- Linux Shell脚本编程-语句控制
- “校园知网”5月5日冲刺计划书
- inurl:faq.php?action=,什么是财富等级 | 帮助 | 酷狗直播 | 就是歌手多
- mybatis学习1
- The current epoch, 79 is less than the accepted epoch, 5b
- 51单片机数码管表白
- 使用Python获取股市北向资金和南向资金信息
- Reliability, Availability, Serviceability (RAS) 介绍
- 商家分账使用场景流程
- 动态代理及JDK动态代理源码分析
- jpg转换成dwf的方式
- JAVA list实现对象的灵活查找
- jackson序列化首字母大写amp;jackson序列化结果字段名重复
热门文章
- 互联网日报 | 蔚来首款旗舰轿车1月9日发布;抖音电商开启首届抢新年货节;2020年快递业务量达830亿件...
- Python函数参数之*与**用法详解
- 云付注册推荐人怎么填?云付新手怎么操作
- 工信部:禁止外资参与网络出版 外国游戏国内要玩完
- [解锁越狱]诺基亚 Lumia 710 800 最详细的解锁越狱教程
- matlab插值与拟合(命令与示例),matlab插值与拟合(命令与示例)
- matlab计算器设计流程图_基于MATLAB计算器设计与开发
- 德州仪器宣布收购12寸晶圆厂
- Windows自定义开关机的音乐
- Ubuntu18.04系统备份与恢复软件推荐——Systemback