转自台湾师范大学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回溯算法相关推荐

  1. c语言backtrack算法6,一个关于数组回溯算法(backtrack)的通用模式

    今天在LeetCode看到一篇非常有价值的讨论,列举了一系列列数组的回溯算法的通用模式,自己动手一个个完成后,感觉对理解回溯算法的原理有很大帮助. 其实回溯就是按顺序的一种穷举,但是它会设定停止条件和 ...

  2. 回溯算法——算法总结(四)

    回溯算法也叫试探法,它是一种系统地搜索问题的解的方法.回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试.用回溯算法解决这个问题的一般步骤为: 1.定义一个解空间.它包括问题 ...

  3. 算法分析结课总结--回溯算法

    以下是回溯算法的经典框架结构: 1 //t:递归的深度,也就是对象的层数.因此每次的回溯遍历都以深度为参数. 2 void backtrack (int t) 3 { 4 if(t>n) //n ...

  4. 回溯java算法_聊聊算法——回溯算法

    "递归只应天上有,迭代还须在人间",从这句话我们可以看出递归的精妙,确实厉害,递归是将问题规模逐渐减小, 然后再反推回去,但本质上是从最小的规模开始,直到目标值,思想就是数学归纳法 ...

  5. 回溯法遵循深度优先吗_闲来刷下「回溯算法」

    定义 ❝ 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就"回溯"返回,尝试别的路径.回溯法是一种选优搜索法,按选优条件向 ...

  6. 一篇带你搞透回溯算法

    回溯算法应用场合 回溯算法和递归算法一般同时出现,一般递归算法的下面就是回溯的逻辑. 一般说递归函数,其实就是回溯函数.回溯一般不会单独出现. 回溯法其实是一个纯暴力的搜索算法.有些问题用for循环搜 ...

  7. 五大常用经典算法—回溯算法

    原文作者:labuladong 原文地址:回溯算法套路详解 读完本文,你可以去力扣拿下如下题目: 46.全排列 51.N皇后 解决一个回溯问题,实际上就是一个决策树的遍历过程.你只需要思考 3 个问题 ...

  8. 回溯算法团灭子集、排列、组合问题

    回溯算法团灭子集.排列.组合问题 一.子集 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = [1,2,3] ...

  9. 回溯算法详解之全排列、N皇后问题

    回溯算法详解 回溯算法框架.解决一个回溯问题,实际上就是一个决策树的遍历过程.你只需要思考 3 个问题: 1.路径:也就是已经做出的选择. 2.选择列表:也就是你当前可以做的选择. 3.结束条件:也就 ...

最新文章

  1. Android不使用支持库请求运行时权限
  2. 提高语音识别成功率的解决方案思路一
  3. Win2003下Exchange2003部署图解之二
  4. linux 释放进程res_linux内存查看及释放
  5. 原子性 atomic 类用法
  6. 下标索引必须为正整数类型或逻辑类型_python量化基础 | 变量和简单的数据类型,零基础都可以看懂...
  7. nodejs爬虫基础(二)
  8. Linux Shell脚本编程-语句控制
  9. “校园知网”5月5日冲刺计划书
  10. inurl:faq.php?action=,什么是财富等级 | 帮助 | 酷狗直播 | 就是歌手多
  11. mybatis学习1
  12. The current epoch, 79 is less than the accepted epoch, 5b
  13. 51单片机数码管表白
  14. 使用Python获取股市北向资金和南向资金信息
  15. Reliability, Availability, Serviceability (RAS) 介绍
  16. 商家分账使用场景流程
  17. 动态代理及JDK动态代理源码分析
  18. jpg转换成dwf的方式
  19. JAVA list实现对象的灵活查找
  20. jackson序列化首字母大写amp;jackson序列化结果字段名重复

热门文章

  1. 互联网日报 | 蔚来首款旗舰轿车1月9日发布;抖音电商开启首届抢新年货节;2020年快递业务量达830亿件...
  2. Python函数参数之*与**用法详解
  3. 云付注册推荐人怎么填?云付新手怎么操作
  4. 工信部:禁止外资参与网络出版 外国游戏国内要玩完
  5. [解锁越狱]诺基亚 Lumia 710 800 最详细的解锁越狱教程
  6. matlab插值与拟合(命令与示例),matlab插值与拟合(命令与示例)
  7. matlab计算器设计流程图_基于MATLAB计算器设计与开发
  8. 德州仪器宣布收购12寸晶圆厂
  9. Windows自定义开关机的音乐
  10. Ubuntu18.04系统备份与恢复软件推荐——Systemback