生成0~n(n≤255)的一个全排列的程序代码
- 格式:docx
- 大小:33.50 KB
- 文档页数:2
全排列递归算法c语言
全排列是一种将一组元素进行排列得到所有可能的组合的算法。
递归是一种重复调用函数本身的方法,可以用来实现全排列算法。
以下是一个使用递归算法实现全排列的C语言代码示例:// 交换数组中两个元素的位置
// 递归生成全排列
// 将第i个元素与第start个元素交换位置 // 递归生成剩余元素的全排列
// 恢复数组的原始顺序
这段代码使用了递归的方式生成数组 `arr` 的全排列。
`permute` 函数接受一个数组、起始位置 `start` 和结束位置`end` 作为参数。
在每一次递归调用中,它将当前位置的元素与后续位置的元素依次交换,并递归生成剩余元素的全排列。
当`start` 等于 `end` 时,表示已经完成了一种排列,将其打印出来。
运行上述代码,将会输出以下结果:
1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2
```
这些结果是给定数组 `[1, 2, 3]` 的所有全排列。
排序—时间复杂度为O(n2)的三种排序算法1 如何评价、分析⼀个排序算法?很多语⾔、数据库都已经封装了关于排序算法的实现代码。
所以我们学习排序算法⽬的更多的不是为了去实现这些代码,⽽是灵活的应⽤这些算法和解决更为复杂的问题,所以更重要的是学会如何评价、分析⼀个排序算法并在合适的场景下正确使⽤。
分析⼀个排序算法,主要从以下3个⽅⾯⼊⼿:1.1 排序算法的执⾏效率1)最好情况、最坏情况和平均情况时间复杂度待排序数据的有序度对排序算法的执⾏效率有很⼤影响,所以分析时要区分这三种时间复杂度。
除了时间复杂度分析,还要知道最好、最坏情况复杂度对应的要排序的原始数据是什么样的。
2)时间复杂度的系数、常数和低阶时间复杂度反映的是算法执⾏时间随数据规模变⼤的⼀个增长趋势,平时分析时往往忽略系数、常数和低阶。
但如果我们排序的数据规模很⼩,在对同⼀阶时间复杂度的排序算法⽐较时,就要把它们考虑进来。
3)⽐较次数和交换(移动)次数内排序算法中,主要进⾏⽐较和交换(移动)两项操作,所以⾼效的内排序算法应该具有尽可能少的⽐较次数和交换次数。
1.2 排序算法的内存消耗也就是分析算法的空间复杂度。
这⾥还有⼀个概念—原地排序,指的是空间复杂度为O(1)的排序算法。
1.3 稳定性如果待排序的序列中存在值相等的元素,经过排序之后,相等元素之间原有的先后顺序不变,那么这种排序算法叫做稳定的排序算法;如果前后顺序发⽣变化,那么对应的排序算法就是不稳定的排序算法。
在实际的排序应⽤中,往往不是对单⼀关键值进⾏排序,⽽是要求排序结果对所有的关键值都有序。
所以,稳定的排序算法往往适⽤场景更⼴。
2 三种时间复杂度为O(n2)的排序算法2.1 冒泡排序2.1.1 原理两两⽐较相邻元素是否有序,如果逆序则交换两个元素,直到没有逆序的数据元素为⽌。
每次冒泡都会⾄少让⼀个元素移动到它应该在的位置。
2.1.2 实现void BubbleSort(int *pData, int n) //冒泡排序{int temp = 0;bool orderlyFlag = false; //序列是否有序标志for (int i = 0; i < n && !orderlyFlag; ++i) //执⾏n次冒泡{orderlyFlag = true;for (int j = 0; j < n - 1 - i; ++j) //注意循环终⽌条件{if (pData[j] > pData[j + 1]) //逆序{orderlyFlag = false;temp = pData[j];pData[j] = pData[j + 1];pData[j + 1] = temp;}}}}测试结果2.1.3 算法分析1)时间复杂度最好情况时间复杂度:当待排序列已有序时,只需⼀次冒泡即可。
全排列的生成算法全排列的生成算法就是对于给定的字符集,用有效的方法将所有可能的全排列无重复无遗漏地枚举出来。
任何n 个字符集的排列都可以与1~n的n个数字的排列一一对应,因此在此就以n个数字的排列为例说明排列的生成法。
n个字符的全体排列之间存在一个确定的线性顺序关系。
所有的排列中除最后一个排列外,都有一个后继;除第一个排列外,都有一个前驱。
每个排列的后继都可以从它的前驱经过最少的变化而得到,全排列的生成算法就是从第一个排列开始逐个生成所有的排列的方法。
全排列的生成法通常有以下几种:字典序法递增进位数制法递减进位数制法邻位交换法递归类算法1.字典序法字典序法中,对于数字1、2、3......n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。
例如对于5个数字的排列12354和12345,排列12345在前,排列12354在后。
按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的是54321。
字典序算法如下:设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即j=max{i|pi<pi+1}2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)3)对换pi,pk4)再将pj+1......pk-1pkpk+1pn倒转得到排列p’’=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个下一个排列。
例如839647521是数字1~9的一个排列。
从它生成下一个排列的步骤如下:自右至左找出排列中第一个比右边数字小的数字4 839647521在该数字后的数字中找出比4大的数中最小的一个5 839647521将5与4交换 839657421将7421倒转 839651247所以839647521的下一个排列是839651247。
c语言 n个数值选出最大m个数最优算法选择最大的n个数的问题在计算机科学领域中是一个经典的算法问题。
在本文中,我们将探讨一种最优算法来解决这个问题,该算法称为"堆排序"。
堆排序是一种基于二叉堆的排序算法,它具有时间复杂度为O(nlogn)的优势。
在堆排序中,我们使用一个称为"堆"的数据结构来选择最大的m个数。
让我们了解一下堆是什么。
堆是一种完全二叉树,其中每个节点的值都大于或等于其子节点的值(称为"最大堆")或小于或等于其子节点的值(称为"最小堆")。
在我们的问题中,我们将使用最大堆。
现在,让我们来看看如何使用堆排序算法来选择最大的m个数。
步骤1:建立最大堆我们需要将给定的n个数构建成一个最大堆。
我们可以通过从下到上,从右到左地调整每个节点的位置来实现。
具体来说,我们从最后一个非叶子节点开始,依次将每个节点与其子节点进行比较,并交换位置,直到满足最大堆的条件。
步骤2:选择最大的m个数一旦我们建立了最大堆,我们就可以开始选择最大的m个数了。
我们可以通过从堆的根节点开始,依次将根节点与最后一个叶子节点进行交换,并将最大的数放在一个新的数组或列表中。
然后,我们将最后一个叶子节点从堆中删除,并重新调整堆,使其满足最大堆的条件。
我们重复这个过程m次,直到我们选择了最大的m个数。
步骤3:输出最大的m个数我们将输出我们选择的最大的m个数。
这些数将按照从大到小的顺序排列。
现在,我们来看一个具体的例子,以更好地理解堆排序算法。
假设我们有一个包含10个数的数组:[5, 20, 3, 8, 15, 12, 16, 7, 25, 10],我们要选择其中最大的3个数。
步骤1:建立最大堆我们将数组构建成一个最大堆。
通过比较每个节点与其子节点的值,并交换位置,我们可以得到以下的最大堆:[25, 20, 16, 10, 15, 12, 3, 7, 5, 8]步骤2:选择最大的3个数现在,我们从最大堆中选择最大的3个数。
c语言字符串全排列算法在计算机科学中,字符串全排列算法是一种常见的算法,它用于生成一个字符串的所有可能排列。
这对于测试算法或解决一些涉及字符串的问题非常有用。
下面,我们将介绍一种使用C语言实现字符串全排列的算法。
一、算法概述字符串全排列是指将一个字符串的所有字符重新排列,形成所有可能的字符串。
这种方法可以生成所有可能的字符串,其中每个字符都可能出现在任何位置。
二、C语言实现下面是一个使用C语言实现字符串全排列的简单示例代码:```c#include <stdio.h>#include <string.h>void swap(char *x, char *y) {char temp;temp = *x;*x = *y;*y = temp;}void permute(char *a, int l, int r) {int i;if (l == r) {printf("%s\n", a);} else {for (i = l; i <= r; i++) {swap((a + l), (a + i));permute(a, l + 1, r);swap((a + l), (a + i)); // backtrack}}}int main() {char str[100];printf("Enter a string: ");fgets(str, sizeof(str), stdin); // read string from user inputpermute(str, 0, strlen(str) - 1); // call the function to generate all permutationsreturn 0;}```这段代码首先定义了一个交换函数`swap()`,用于交换两个字符的位置。
然后,`permute()`函数用于生成字符串的全排列。
【codeup】1959:全排列及全排列算法详解题⽬描述给定⼀个由不同的⼩写字母组成的字符串,输出这个字符串的所有全排列。
我们假设对于⼩写字母有'a' < 'b' < ... < 'y' < 'z',⽽且给定的字符串中的字母已经按照从⼩到⼤的顺序排列。
输⼊输⼊只有⼀⾏,是⼀个由不同的⼩写字母组成的字符串,已知字符串的长度在1到6之间。
输出输出这个字符串的所有排列⽅式,每⾏⼀个排列。
要求字母序⽐较⼩的排列在前⾯。
字母序如下定义:已知S = s1s2...sk , T = ,则S < T 等价于,存在p (1 <= p <= k),使得s1 = t1, s2 = t2, ..., sp - 1 = tp - 1, sp < tp成⽴。
注意每组样例输出结束后接⼀个空⾏。
样例输⼊xyz样例输出xyzxzyyxzyzxzxyzyx提⽰⽤STL中的next_permutation会⾮常简洁。
思路:由于题⽬提⽰使⽤next_permutation会简洁,所以这⾥我们使⽤此⽅法。
1 #include<iostream>2 #include<stdio.h>3 #include<queue>4 #include<string>5 #include<string.h>6 #include<algorithm>7using namespace std;89char a[10];1011int main()12 {13int n;14while(scanf("%s",a)!=EOF)15 {16 n=strlen(a);17do18 {19 printf("%s\n",a);20 }while(next_permutation(a,a+n));21 puts("");22 }23return0;24 }C++/STL中定义的next_permutation和prev_permutation函数是⾮常灵活且⾼效的⼀种⽅法,它被⼴泛的应⽤于为指定序列⽣成不同的排列。
c语言排列组合代码C语言排列组合是编程中非常重要的一个概念,它可以帮助我们解决很多实际问题。
下面我将为你介绍一些关于C语言排列组合的基本知识,并提供一些示例代码帮助你更好地理解。
首先,我们需要了解排列和组合这两个概念的区别。
排列指的是从一组元素中选取一部分进行排列放置,而组合则是从一组元素中选取一部分进行组合放置。
换句话说,排列要考虑元素的顺序,而组合则不考虑元素的顺序。
那么,如何实现C语言中的排列组合呢?一、排列1.全排列全排列是指将给定的一组元素进行全面的排列,即将每个元素都当作一个起始元素,与其他元素进行交换得到所有可能的排列。
以下是一个示例代码:```#include <stdio.h>// 交换两个元素的值void swap(char *a, char *b) {char temp = *a;*a = *b;*b = temp;}// 输出全排列结果void permute(char *str, int start, int end) {if (start == end) {printf("%s\n", str);} else {for (int i = start; i <= end; i++) {swap((str + start), (str + i));permute(str, start + 1, end);swap((str + start), (str + i)); // 恢复原始位置 }}}int main() {char str[] = "abc";int size = strlen(str);permute(str, 0, size - 1);return 0;}```2.部分排列部分排列是指从一组元素中选取一部分进行排列。
以下是一个示例代码:```#include <stdio.h>// 输出部分排列结果void partial_permute(char *str, int start, int end, int r) {if (r == 0) {for (int i = 0; i < start; i++) {printf("%c", str[i]);}printf("\n");} else {for (int i = start; i <= end; i++) {swap((str + start), (str + i));partial_permute(str, start + 1, end, r - 1);swap((str + start), (str + i)); // 恢复原始位置}}}int main() {char str[] = "abcd";int size = strlen(str);int r = 3; // 选取3个元素进行排列partial_permute(str, 0, size - 1, r);return 0;}```二、组合组合是指从一组元素中选取一部分进行组合。
java疯狂练习(带源代码)【程序1】题⽬:古典问题:有⼀对兔⼦,从出⽣后第3个⽉起每个⽉都⽣⼀对兔⼦,⼩兔⼦长到第三个⽉后每个⽉⼜⽣⼀对兔⼦,假如兔⼦都不死,问每个⽉的兔⼦总数为多少?1.程序分析:兔⼦的规律为数列1,1,2,3,5,8,13,21....import java.util.Scanner;public class rabbit {public static void main(String[] args) {int number = 1, month;int tmp1 = 1, tmp2 = 1;Scanner sc = new Scanner(System.in);System.out.println("请输⼊第⼏个⽉:");month = sc.nextInt();for (int i = 1; i <= month; i++) {if (i <= 2)number = 1;else {number = tmp1 + tmp2;// 前两个⽉兔⼦数之和tmp2 = tmp1;// 前第⼆个⽉tmp1 = number;// 前⼀个⽉}System.out.println("第" + i + "个⽉的兔⼦数是:" + number);}}}【程序2】题⽬:判断101-200之间有多少个素数,并输出所有素数。
1.程序分析:判断素数的⽅法:⽤⼀个数分别去除2到sqrt(这个数),如果能被整除,public class timu2 {public static void main(String[] args) {int sum = 0;for (int i = 101; i <= 200; i++)for (int j = 2; j <= i; j++) {if (i % j == 0 && i == j) {} else if (i % j == 0 && i != j)break;}System.out.println("101-200之间有:"+sum+"个素数");}}则表明此数不是素数,反之是素数。
1.2 排 列教 学 过 程 备 注教学 引入教学 内 容 一、排列及其奇偶性:1、排列:1)n 个数码1,2,…,n组成的一个有序组i1i2…i n称为一个n元排列.注:n元排列就是n个不同元素的全排列,n个数码 1,2,…,n的排列共有:n(n-1)…21=n! (个)(用提问的方式)n元排列中的n!个排列中,排列123…n称为标准排列,它具有自然顺序, 而在其它n!-1 个排列中,都或多式少地违反了自然顺序。
2)在一个排列中若有较大的数码排在较小的数码之前(不一定定相邻),把 这种大小颠倒的情形称为该排列的一个反序(或逆序)。
在一个排列中出现的反序总数叫做这个排列的反序数,记作p(i1i2…i n).如:p(2431)=4,p(534162)=9。
提问:如何计算 n 元排列的反序数?一个排列i1i2…i n的反序数p(i1i2…i n)的计算方法归纳如下:▲先看有多少个数码排在 1 的前面,设为m1 个,那么就有m1 个数码与 1 构成 反序;然后把 1 划去,再看有多少个数码排在 2 的前面,设为m2个,那么就有m2 个数码与 2构成反序;再划去2,……由此可得:p (i1i2…i n)=m1+m2+…+m n(P6 例 2)▲p (i1i2…i n)=i1 后面比 i1 小的数码的个数+i2 后面比 i2 小的数码的个数 + ……+i n-1 后面比 i n-1 小的数码的个数.或p (i1i2…i n)=i n 前面比 i n 大的数码的个数+ i n-1 前面比 i n-1 大的数码的个数 + ……+i2 前面比 i2 大的数码的个数.(P6 例 3).例 1由数码 1,2,3,4构成的全部 4 元排列共有 4!=24 个,它们是:1234,1243,1324,1342,1423,14322134,2143,2314,2341,2413,24313124,3142,3214,3241,3412,34214123,4132,4213,4231,4312,4321.定义 2 反之, 在一个排列中, 如果一个较小的数码排在一个较大的数码之前, 那么称这两个数码构成一个顺序.给定由数码 1,2,…,n构成的一个排列i1i2…i n后,我们可以这样来例 2p (986754231)=8+6+6+5+4+2+2+1+0=34 .例 3由数码 1, 2, …,n构成的反序数最多的排列是哪一个?反序数是多少?显然任意两个数码都能构成反序的排列其反序数最大. 因此,反序数最大的 排列是n (n-1)…21,其反序数是p [n(n-1)…2 1]=( n-1)+( n-2)+…+2+1=21n(n-1).定义 3 如果p (i1i2…i n)是偶数(零也算做偶数),则称i1i2…i n为偶排列;如果p (i1i2…i n)是奇数,则称i1i2…i n为奇排列.例如,1243是奇排列,2143 是偶排列.在全部的 6个 3 元排列中,123,231,312 是偶排列,而 132,213,321是奇 排列. 在这里,奇、偶排列各占一半. 一般说来,在所有n!个n元排列中,奇排列与偶排列各占一半. 为了证明这一结论,还需要进一步研究排列的奇偶性. 把一个排列中某两个数码的位置互换,而其余的数码保持不动,就得到一个 新排列,这样的一个变换称为对换. 例 4 p (4312)=5, 4312是奇排列, 对换数码 1 与 4得到排列 1342, p (1342) =2,1342 是偶排列. 定理 1.2.1 一次对换改变排列的奇偶性. 证 情形 1 被对换的两个数码在排列中是相邻的情形. 设 … j k … (1) 经对换 j 与k 变成排列 … k j … (2) 这里“…”表示不变动的数码,显然在(1)与(2)中,j 和 k 与前后不动的数码 构成的反序或顺序都是相同的,不同的只是 j 与 k 的次序变了,若原来构成反序, 经对换后,则 k 与 j 不构成反序,这样排列(2)比排列(1)的反序数少 1. 反之,则 排列(2)比(1)的反序数多 1. 无论是减少 1 或增加 1,排列的奇偶性都改变了. 情形 2 被对换的两个数码不相邻. 设排列为 … j i 1 i 2 … i s k …, (3) 对换 j 与 k ,得到排列 … k i 1 i 2 … i s j …. (4) 不难看出,这样一个不相邻的两个数码的对换可以通过若干个相邻两个数码 的对换来实现. 从(3)出发,将 k 与 i s 对换,再与 i s -1对换,…,与 i 1 对换,最后 与 j 对换,共经 s +1次相邻数码的对换,排列(3)变成 … k j i 1 i 2 … i s …. (5) 再从(5)出发,把 j 与 i 1, i 2,…, i s 一个一个地对换,共经过 s 次相邻数码的对 换,排列(5)就变成了排列(4). 因此,j 与 k 的直接对换可经 2s +1 次相邻两个数 码的对换来实现. 由于2s +1是奇数, 根据情形1, 排列(3)与(4)的奇偶性不同. □ 推论 1.2.2 奇数次对换改变排列的奇偶性,偶数次对换不改变排列的奇偶 性. 有了定理 1.2.1,便可证明定理 1.2.3 在 n ! (n ³ 2)个 n 元排列中,奇偶排列的个数相等,各有 2 ! n 个. 证 设在这 n !个 n 元排列中,有 p 个互不相同的奇排列,q 个互不相同的偶 排列,则 p +q=n !. 对这 p 个不同的奇排列都施行同一个对换,例如都对换数码 1 与 2,由定理 1.2.1, 得到p 个不同的偶排列,而偶排列只有q 个,所以,p £ q . 同理,对 q 个互不相同的偶排列都施行同一个对换,例如都对换数码1与2, 由定理1.2.1,得到q 个互不相同的奇排列,于是,q £ p . 因此,q=p= 2! n . □ 最后再证明一个结论.定理 1.2.4 由数码 1, 2, …, n 构成的任一个 n 元排列 i 1 i 2…i n 都可以经过 若干次对换变成排列 1 2 … n , 并且所作对换的次数与p (i 1 i 2…i n )有相同的奇 偶性.证 对排列 i 1 i 2…i n 讲,若 i 1¹1 时,对换 i 1 与 1 得新排列 1 j 2 j 3… j n ,这里 j 2 j 3… j n 是数码 2, 3, …, n 构成的排列. 若j 2¹2,对换 j 2 与 2 得新排列 1 2 k 3… k n ,其中 k 3 k 4…k n 是数码 3, 4,…,n 构成的排列,因 n 是有限数,如此下去,排列i1i2…i n就变成了排列 12…n.若i1i2…i n是偶排列,则所作的对换次数一定是偶数,因为 1 2 … n也是偶排 列.若i1i2…i n是奇排列,则所作的对换次数一定是奇数,因为将i1i2…i n对换 成 1 2…n时,改变了排列的奇偶性. □小结与作业课堂小结本节内容分为下面四个问题讲:1. 为什么要讲排列?(为了定义n阶行列式.)2. 排列的定义(P6 定义1).3. 偶排列,奇排列,排列的反序数.4. 对换改变排列的奇偶性(P7 定理 1.2.1).注:在讲定理 1.2.3 时,必须强调对 p 个奇排列都施行同一个对换,才 能得到 p 个不同的偶排列. 因为两个不同的奇排列,如果对换的数码不相同, 有可能得到同一个偶排列. 类似地,对偶排列也要注意到这个问题.本课作业本课教育评注(课堂设计理念,实际教学效果及改进设想)。
排列组合的一些公式及推导(非常详细易懂)绪论:加法原理、乘法原理分类计数原理:做一件事,有n类办法,在第1类办法中有m1种不同的方法,在第2类办法中有m2种不同的方法,…,在第n类办法中有mn种不同的方法,那么完成这件事共有N=m1+m2+…+mn 种不同的方法。
分步计数原理:完成一件事,需要分成n个步骤,做第1步有m1种不同的方法,做第2步有m2种不同的方法,…,做第n步有mn种不同的方法,那么完成这件事共有N=m1×m2×⋯×mn种不同的方法。
区别:分类计数原理是加法原理,不同的类加起来就是我要得到的总数;分步计数原理是乘法原理,是同一事件分成若干步骤,每个步骤的方法数相乘才是总数。
排列问题排列数从n个不同元素种取出m(m≤n)个元素的所有不同排列的个数,叫做从n个不同元素种取出m个元素的排列数,用符号Amn表示。
排列数公式Amn=n(n−1)(n−2)⋯(n−m+1)=n!(n−m)!,n,m∈N∗,并且m≤n(规定0!=1)推导:把n个不同的元素任选m个排序,按计数原理分步进行:取第一个:有n种取法;取第二个:有(n−1)种取法;取第三个:有(n−2)种取法;……取第m个:有(n−m+1)种取法;根据分步乘法原理,得出上述公式。
排列数性质Amn=nAm−1n−1 可理解为“某特定位置”先安排,再安排其余位置。
Amn=mAm−1n−1+Amn−1 可理解为:含特定元素的排列有mAm−1n−1,不含特定元素的排列为Amn−1。
组合问题组合数从n个不同元素种取出m(m≤n)个元素的所有不同组合的个数,叫做从n个不同元素种取出m个元素的组合数,用符号Cmn表示。
组合数公式Cmn=AmnAmm=n(n−1)(n−2)⋯(n−m+1)m!=n!m!(n−m)!,n,m∈N∗,并且m≤nC0n=Cnn=1证明:利用排列和组合之间的关系以及排列的公式来推导证明。
将部分排列问题Amn分解为两个步骤:第一步,就是从n个球中抽m个出来,先不排序,此即组合数问题Cmn;第二步,则是把这m个被抽出来的球排序,即全排列Amm。
C语⾔实现全排列和回溯法总结⼀、递归实现全排列1 #include"cstdio"2int A[50];3void print_permutation(int n,int *A,int cur){4if(cur==n){5for(int i=0;i<n;i++)6 printf("%d",A[i]);7 printf("\n");8 }9else for(int j=1;j<n+1;j++){10int ok=1;11for(int k=0;k<cur;k++)12if(A[k]==j)13 ok=0;14if(ok){15 A[cur]=j;16 print_permutation(n,A,cur+1);17 }18 }19 }20int main(){21int n;22 scanf("%d",&n);23 print_permutation(n,A,0);24return0;25 }View Code⼆、解答树1 #include <string.h>2 #include <iostream>34using namespace std;5const int N = 99999999; //输⼊排序的个数的最⼤值6int record[N]; //记录每次排序的序列7int visited[N]; //标记节点是否被访问过8int n; //输⼊节点的数⽬9int totalSize = 0;10void DFS(int start){11if(start>=n){ //递归出⼝12for(int i=0;i<n;i++){13 cout<<record[i]<<"";14 }15 totalSize++;16 cout<<endl;17return;18 }19for(int i=1;i<=n;i++){ //深度遍历节点,并标记已经访问过的节点20if(visited[i]==0){21 visited[i] = 1;22 record[start] = i;23 DFS(start+1); //递归遍历24 visited[i] = 0; //回退时标记回退的节点为未被访问节点25 }26 }27 }2829int main()30 {31 cin>>n;32 memset(visited,0,n);33 DFS(0);34 cout<<"totalSize = "<<totalSize<<endl;35return0;36 }View Code三、调⽤next_permutation()⽅法四、回溯法总结1、⼋皇后问题代码1 #include<iostream>2 #include<math.h>3using namespace std;4int n=8; 5int rows[8];//存储n⾏的第⼏列6int j=0;7bool Is(int row){8for(int i=1;i<row+1;i++){9if(rows[row-i]==rows[row]-i||rows[row-i]==rows[row]+i||rows[row]==rows[row-i]) 10return false;11 }12return true;13 }14void start(int row){15if(row==n)16 j++;17else {18for(int col=0;col<n;col++){19 rows[row]=col;20if(Is(row)){21 printf("%d %d\n",row,rows[row]);22 start(row+1);23 }24 }25 }26 }27int main(){28 start(0);29 printf("%d\n",j);30return0;31 }总结:在全排列和⼋皇后问题中,均使⽤了递归回溯。
01:查找特定的值∙∙提交∙统计∙提问总时间限制:1000ms内存限制:65536kB描述在一个序列(下标从1开始)中查找一个给定的值,输出第一次出现的位置。
输入第一行包含一个正整数n,表示序列中元素个数。
1 <= n <= 10000。
第二行包含n个整数,依次给出序列的每个元素,相邻两个整数之间用单个空格隔开。
元素的绝对值不超过10000。
第三行包含一个整数x,为需要查找的特定值。
x的绝对值不超过10000。
输出若序列中存在x,输出x第一次出现的下标;否则输出-1。
02:输出最高分数的学生姓名描述输入学生的人数,然后再输入每位学生的分数和姓名,求获得最高分数的学生的姓名。
输入第一行输入一个正整数N(N<= 100),表示学生人数。
接着输入N行,每行格式如下:分数姓名分数是一个非负整数,且小于等于100;姓名为一个连续的字符串,中间没有空格,长度不超过20。
数据保证最高分只有一位同学。
输出获得最高分数同学的姓名。
来源习题(13-1)03:不高兴的津津描述津津上初中了。
妈妈认为津津应该更加用功学习,所以津津除了上学之外,还要参加妈妈为她报名的各科复习班。
另外每周妈妈还会送她去学习朗诵、舞蹈和钢琴。
但是津津如果一天上课超过八个小时就会不高兴,而且上得越久就会越不高兴。
假设津津不会因为其它事不高兴,并且她的不高兴不会持续到第二天。
请你帮忙检查一下津津下周的日程安排,看看下周她会不会不高兴;如果会的话,哪天最不高兴。
输入包括七行数据,分别表示周一到周日的日程安排。
每行包括两个小于10的非负整数,用空格隔开,分别表示津津在学校上课的时间和妈妈安排她上课的时间。
输出包括一行,这一行只包含一个数字。
如果不会不高兴则输出0,如果会则输出最不高兴的是周几(用1, 2, 3, 4, 5, 6, 7分别表示周一,周二,周三,周四,周五,周六,周日)。
如果有两天或两天以上不高兴的程度相当,则输出时间最靠前的一天。