枚举-递归-回溯
搜索算法入门详解

搜索算法⼊门详解什么是搜索算法搜索算法是利⽤计算机的⾼性能来有⽬的的穷举⼀个问题解空间的部分或所有的可能情况,从⽽求出问题的解的⼀种⽅法。
现阶段⼀般有枚举算法、深度优先搜索、⼴度优先搜索、A*算法、回溯算法、蒙特卡洛树搜索、散列函数等算法。
在⼤规模实验环境中,通常通过在搜索前,根据条件降低搜索规模;根据问题的约束条件进⾏剪枝;利⽤搜索过程中的中间解,避免重复计算这⼏种⽅法进⾏优化。
搜索⽅式⾸先给⼤家扫个盲在搜索中,不仅仅只有常见的递归式搜索,也存在着⼀部分正向迭代式搜索,但是在真正的使⽤中递归式搜索占到了绝⼤多数,基本上所有的递归式搜索⽤是递归都可以实现只不过代价⽐较⼤⽐如我们想要求出数字 1 - 3之间所有数字的全排列这个问题很简单,简单到不想⽤⼿写。
还是写⼀下吧对于这个问题我们只⽤三重循环就可以完全搞定它int n = 3;for(int i = 1;i <= n ;i ++){for(int j = 1;j <= n ;j ++){for(int k = 1;k <= n; k++){if(i != j && i != k && j != k){printf("%d %d %d\n",i ,j ,k);}}}}这个时候有同学就会问了,既然⽤递推就可以实现我们的搜索那么我们为什么还要费劲的去写递归呢?原因是之前举的哪⼀个例⼦规模很⼩,如果此时我们讲n 换成10 我们需要枚举 1 - 10的全排列那么你⽤递推的话代码⼤致式这样的int n = 3;for(int i = 1;i <= n ;i ++){for(int j = 1;j <= n ;j ++){for(int k = 1;k <= n; k++){for(int o = 1; 0 <= n ;o++){for(int p = 1;p <= n ; p++){for(){for().......不写了我吐了}}}}}}⾸先不说你有没有⼼情实现,光是变量的字母引⽤就够你喝⼀壶了这⾥n = 10 还没超过26,那如果超过了26,你岂不是要把汉字搬来了....这⾥就暴露出⼀个问题。
回溯算法的应用场景

回溯算法的应用场景回溯算法是一种经典的问题求解算法,常用于解决组合问题、排列问题、搜索问题等。
它通过不断地尝试和回退来寻找问题的解,可以在有限的时间内找到问题的所有解,或者找到满足特定条件的解。
下面将介绍回溯算法的几个常见应用场景。
1. 组合问题组合问题是指从给定的一组元素中选取若干个元素,使得它们满足一定的条件。
例如,在一副扑克牌中选取若干张牌,使得它们的点数之和等于给定的目标值。
回溯算法可以通过枚举所有可能的组合来解决这类问题。
具体实现时,可以使用递归或迭代的方式进行求解。
2. 排列问题排列问题是指从给定的一组元素中选取若干个元素进行全排列,使得每个元素都不重复出现。
例如,在一组数字中找出所有可能的排列。
回溯算法可以通过枚举所有可能的排列来解决这类问题。
具体实现时,同样可以使用递归或迭代的方式进行求解。
3. 搜索问题搜索问题是指在给定的搜索空间中找到满足一定条件的解。
例如,在迷宫中找到从起点到终点的路径,或者在一个图中找到满足特定条件的子图。
回溯算法可以通过不断地尝试和回退来搜索所有可能的解,并找到满足条件的解。
在搜索问题中,通常使用深度优先搜索来实现回溯算法。
4. 数独问题数独问题是指在一个9×9的网格中填入1至9的数字,使得每行、每列和每个小方格中的数字均不重复。
回溯算法可以通过逐个地尝试填入数字,并不断检查当前状态是否满足条件来解决数独问题。
当无法继续填入数字时,回溯算法会回退到前一步继续尝试其他可能的解。
5. 棋盘问题棋盘问题是指在一个给定大小的棋盘上放置一定数量的棋子,使得它们满足一定的规则。
例如,在N皇后问题中,要在一个N×N大小的棋盘上放置N个皇后,使得它们任意两个皇后都不在同一行、同一列或同一对角线上。
回溯算法可以通过逐行地尝试放置皇后,并检查每次放置是否满足规则来解决这类问题。
回溯算法的应用场景不仅限于上述几个例子,还涉及到许多其他问题,如密码破解、迷宫生成、单词搜索等。
八皇后问题详细的解法

若无法放下皇后则回到上一行, 即回溯
当n行的皇后都已确定后,我们 就找到了一种方案
check2 (int a[ ],int n)
queen21(例) 1 b加约束的枚举算法{//i多nt次i; 被调用,只是一重循环
{int a[9]; for (a[1]=1;a[1]<=8;a[1]++) for (a[2]=1;a[2]<=8;a[2]++)
八皇后问题
1
1八皇后问题背景 2盲目的枚举算法 3加约束的枚举算法 4回溯法及基本思想 5 回溯法应用 6八皇后问题的递归回溯算法 7八皇后问题的非递归回溯算法
2
【背景】 八皇后问题是一个以国际象棋为背
景的问题: 如何能够在 8×8 的国际象棋棋盘上
放置八个皇后,使得任何一个皇后都 无法直接吃掉其他的皇后?为了达到 此目的,任两个皇后都不能处于同一 条横行、纵行或斜线上。
for(a[8]=1;a[8]<=8;a[8]++) 此算法可读性很好,
{if (check(a,8)==0)continue; 体现了“回溯”。但
else for(i=1;i<=8;i+nt(a[i]); }
题,而不能解决任意
}}}}}}}
的n皇后问题。
18
2 回溯法应用-算法说明
按什么顺序去搜? 目标是没有漏网之鱼,尽量速度快。
5
2 【问题设计】盲目的枚举算法
a 盲目的枚举算法
通过8重循环模拟搜索空间中的88个状态;
按枚举思想,以DFS的方式,从第1个皇后在第1列开 始搜索,枚举出所有的“解状态”:
从中找出满足约束条件的“答案状态”。
回溯与递归

回溯与递归
回溯和递归都是算法中常用的概念,通常用于解决一些复杂的问题。
回溯(Backtracking)是一种试探性的算法思想,它可以在解
决问题的过程中进行“回溯”,即通过不断的尝试,找到一条解决问题的路径。
回溯算法通常应用于求解每一个可能的解,并对每一个解进行检查,最终找到一个满足条件的解。
回溯算法通常使用递归的方式实现,每次尝试一个可能的解,如果该解行不通,就回溯到前一步,再尝试另一个可能的解,直到找到一个满足条件的解。
递归(Recursion)是一种算法思想,它将问题的求解转化为
对自身的调用,通常包含一个或多个基准情况和一个或多个递归情况。
递归算法通常需要将问题分解成若干个子问题,然后递归求解每一个子问题的解,最终将子问题的解合并成原问题的解。
递归算法通常用于处理数据结构中的树、图、链表等结构,并可以方便地实现回溯算法。
总的来说,回溯算法是通过尝试所有可能的解来找到一个满足条件的解,而递归算法是通过逐层递归求解子问题的解,最终得到原问题的解。
在实际应用中,回溯算法和递归算法常常相互结合,并且可以通过剪枝等方式进行优化,提高算法的效率。
回溯法的基本概念

回溯法的基本概念回溯法,也叫试探法,是一种基于深度优先搜索的算法。
它是一种非常实用的解决问题的方法,通常用来解决那些需要尝试许多可能性的问题。
在回溯法中,我们需要枚举所有的可能性,并根据条件进行深度搜索,直到找到所有的解或达到终止条件。
回溯法的基本思想是:将问题分成多个小问题来解决,每个小问题都需要尝试不同的解决方案,直到找到最优解或达到终止条件。
当我们尝试的方案不符合要求时,我们需要“回溯”(撤销上一步的操作),尝试其他解决方案。
回溯法的应用非常广泛,比如在图形学、人工智能、网络协议设计等领域都有广泛的应用。
在算法竞赛中,回溯法是一个非常重要的算法,也是我们必须要掌握的算法之一。
使用回溯法的关键在于如何组织搜索空间。
我们需要确定搜索树的遍历顺序和搜索深度,以及如何剪枝搜索空间。
通常情况下,我们可以使用递归函数来实现回溯算法。
这个递归函数需要接收状态参数,在每一次递归调用中,我们需要将状态参数进行更新,并考虑是否达到了终止条件。
在回溯算法的实现中,通常要注意以下几点:1. 前缀和预处理:如果我们需要快速传递状态信息,可以使用前缀和预处理技术。
2. 剪枝:剪枝是一种优化手段,可以在搜索中减少不必要的计算。
比如我们可以根据当前状态进行剪枝,减少搜索量。
3. 记忆化搜索:如果我们需要多次查询相同的状态,可以使用记忆化搜索来优化。
这样可以避免重复计算,提高算法效率。
4. 双向搜索:双向搜索可以从起点和终点同时进行搜索,这样可以减少搜索时间和空间复杂度。
总之,回溯法是一种非常实用的算法,在实际问题求解中具有广泛的应用。
要想掌握回溯法,需要多做题、多思考,掌握其基本原理和常见技巧,逐步提高自己的解题能力。
递归回溯算法

递归回溯算法简介递归回溯算法是一种解决问题的算法思想,它通过不断地尝试所有可能的解决方案,并在每一步中进行回溯,即撤销上一步的选择,直到找到满足条件的解。
这种算法思想通常用于解决组合优化问题,如全排列、子集、背包等。
概念解析•递归:递归是指一个函数调用自身的过程。
在递归回溯算法中,递归函数通常用于尝试解决问题的每一步。
•回溯:回溯是指当无法继续前进时,回退到上一层的过程。
在递归回溯算法中,回溯通常用于撤销上一步的选择,以尝试其他可能的解决方案。
算法框架递归回溯算法的框架通常包括以下几个步骤:1.确定递归函数的输入参数和返回值:通常需要传入当前的状态和已经做出的选择,返回解决方案或最优解。
2.确定递归函数的终止条件:当满足终止条件时,停止继续递归,返回解决方案或最优解。
3.确定每一步的选择范围:根据实际情况,确定可以做出的选择范围。
4.根据选择范围,在每一步中进行递归调用:对每一个选择进行递归调用,尝试解决问题的下一步。
5.在每一步中进行回溯:如果当前选择导致无法继续前进,进行回溯,撤销上一步的选择,尝试其他可能的解决方案。
6.处理结果:根据实际需求,对每一个解决方案进行处理,如输出结果、更新最优解等。
应用场景递归回溯算法在很多问题中都有应用,特别是在组合优化问题中更为常见。
下面列举几个常见的应用场景:1. 全排列全排列是指将一组元素进行排列,列出所有可能的排列情况。
对于一个含有n个元素的集合,全排列的结果共有n!种可能。
算法思路:1.从集合中选择一个元素作为当前位置的元素。
2.使用递归算法求解剩余元素的全排列。
3.当集合中只剩下一个元素时,输出当前排列情况。
4.撤销上一步的选择,尝试其他可能的排列情况。
2. 子集子集是指在一个集合中,取出部分或全部元素形成的集合。
对于一个含有n个元素的集合,子集的结果共有2^n种可能。
算法思路:1.不选择当前元素,进入下一层递归。
2.选择当前元素,进入下一层递归。
如何计算出所有组合

如何计算出所有组合计算所有组合是一个经典的组合问题,可以通过递归、迭代、回溯等多种方法来实现。
下面将介绍其中几种常见的方法。
1.递归方法递归是一种通过函数不断调用自身的方法。
在计算所有组合时,可以使用递归来不断缩小问题规模,直到问题规模为1时返回最终结果。
首先,定义一个递归函数,输入为待组合的列表和每个组合的长度。
然后,递归函数根据组合长度和待组合列表的长度进行条件判断,如果组合长度为1,则直接返回待组合列表的每个元素。
如果待组合列表长度小于等于组合长度,则直接返回待组合列表。
否则,递归调用函数,将问题规模缩小为原始列表中除第一个元素之外的元素列表,组合长度减1、然后将第一个元素依次与新的元素列表中的元素组合,得到新的组合列表。
最后,将新的组合列表与原始列表中的第一个元素组合,并返回。
示例代码如下所示:```pythonif n == 1:return [[x] for x in lst]elif len(lst) <= n:return [lst]else:result = []for i in range(len(lst)-n+1):for ele in rest:result.append([lst[i]] + ele)return result```2.迭代方法迭代方法则是通过循环来计算所有组合。
与递归方法类似,迭代方法需要对问题规模进行缩小,并通过迭代来不断求解子问题。
首先,初始化一个结果列表,并将第一个元素添加到结果列表中。
然后,依次遍历原始列表中的每个元素,将当前元素与结果列表中已有的组合进行组合,并将新的组合添加到结果列表中。
然后,将当前元素与其他元素的组合进行组合,并将新的组合添加到结果列表中。
最后,返回结果列表。
示例代码如下所示:```pythonresult = [[x] for x in lst[0]]for ele in lst[1:]:for lst_ele in result:return result```3.回溯法回溯法是一种通过试错的方法来计算所有组合的方法。
递推-递归-分治-回溯

递推算法在程序编辑过程中,我们可能会遇到这样一类问题,出题者告诉你数列的前几个数,或通过计算机获取了数列的前几个数,要求编程者求出第N项数或所有的数列元素(如果可以枚举的话),或求前N项元素之和。
这种从已知数据入手,寻找规则,推导出后面的数的算法,称这递推算法。
典型的递推算法的例子有整数的阶乘,1,2,6,24,120…,a[n]=a[n-1]*n(a[1]=1);前面学过的2n,a[n]=a[n-1]*2(a[1]=1),菲波拉契数列:1,2,3,5,8,13…,a[n]=a[n-1]+a[n-2](a[1]=1,a[2]=2)等等。
在处理递推问题时,我们有时遇到的递推关系是十分明显的,简单地写出递推关系式,就可以逐项递推,即由第i项推出第i+1项,我们称其为显示递推关系。
但有的递推关系,要经过仔细观察,甚至要借助一些技巧,才能看出它们之间的关系,我们称其为隐式的递推关系。
下面我们来分析一些例题,掌握一些简单的递推关系。
例如阶梯问题:题目的意思是:有N级阶梯,人可以一步走上一级,也可以一步走两级,求人从阶梯底走到顶端可以有多少种不同的走法。
这是一个隐式的递推关系,如果编程者不能找出这个递推关系,可能就无法做出这题来。
我们来分析一下:走上第一级的方法只有一种,走上第二级的方法却有两种(两次走一级或一次走两级),走上第三级的走法,应该是走上第一级的方法和走上第二级的走法之和(因从第一级和第二级,都可以经一步走至第三级),推广到走上第i级,是走上第i-1级的走法与走上第i-2级的走法之和。
很明显,这是一个菲波拉契数列。
到这里,读者应能很熟练地写出这个程序。
在以后的程序习题中,我们可能还会遇到菲波拉契数列变形以后的结果:如f(i)=f(i-1)+2f(i-2),或f(i)=f(i-1)+f(i-2)+f(i-3)等。
我们再来分析一下尼科梅彻斯定理。
定理内容是:任何一个整数的立方都可以写成一串连续的奇数和,如:43=13+15+17+19=64。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、暴力求解法(枚举法/ 穷举法)概念:什么是枚举法?在进行归纳推理时,如果逐个考察了某类事件的所有可能情况,因而得出一般结论,那么这结论是可靠的,这种归纳方法叫做枚举法。
即,把所要解决问题的所有可能性都列举出来,一一试验。
枚举应用简单举例:求1~100之间的素数;求水仙花数;鸡兔同笼问题;百元买百鸡问题;整数(分数)拆分问题;排列问题……枚举算法因为要列举问题的所有可能的答案,所有它具备以下几个特点:1、得到的结果肯定是正确的;2、可能做了很多的无用功,浪费了宝贵的时间,效率低下。
3、通常会涉及到求极值(如最大,最小,最重等)。
4、数据量大的话,可能会造成时间崩溃。
采用枚举算法解题的基本思路:(1)确定枚举对象、枚举范围和判定条件;(2)一一枚举可能的解,验证是否是问题的解下面我们就从枚举算法的的优化、枚举对象的选择以及判定条件的确定,这三个方面来探讨如何用枚举法解题。
例1:百元买百鸡问题:有一个人有一百块钱,打算买一百只鸡。
到市场一看,大鸡三块钱一只,小鸡一块钱三只,不大不小的鸡两块钱一只。
现在,请你编一程序,帮他计划一下,怎么样买法,才能刚好用一百块钱买一百只鸡?算法分析:我们以三种鸡的个数为枚举对象(分别设为x,y,z),以三种鸡的总数(x+y+z)和买鸡用去的钱的总数(x*3+y*2+z/3)为判定条件,穷举各种鸡的个数。
(1)基本算法:for (x=0;x<=100;x++)for (y=0;y<=100;y++)for(z=0;z<=100;z++)if(x+y+z==100 && z%3==0 && x*3+y*2+z/3==100)输出x,y,z(2)优化算法:只需要枚举2种鸡x(x<=33)和y(y<=50),第3种根据约束条件100-x-y可得:for (x=0;x<=33;x++)for (y=0;y<=50;y++){Z=100-x-y;if (z%3==0 && x*3+y*2+z/3==100)输出x,y,z小结:对于枚举算法,加强约束条件,缩小枚举的范围,是程序优化的主要考虑方向。
1.枚举对象的选择问题:在枚举算法中,枚举对象的选择是非常重要的,它直接影响着算法的时间复杂度,选择适当的枚举对象可以获得更高的效率。
如下例:例2:将1,2...9共9个数分成三组,分别组成三个三位数,且使这三个三位数构成1:2:3的比例,试求出所有满足条件的三个三位数。
例如:三个三位数192,384,576满足以上条件。
我们分别设三个数为x,2x,3x,以x为枚举对象,穷举的范围将大大缩小。
例3. 五猴分桃:五只猴子一起摘了一堆桃子,因为太累了,它们商量决定,先睡一觉再分.一会其中的一只猴子来了,它见别的猴子没来,便将这堆桃子平均分成5份,结果多了一个,就将多的这个吃了,并拿走其中的一份.一会儿,第2只猴子来了,他不知道已经有一个同伴来过,还以为自己是第一个到的呢,于是将地上的桃子堆起来,再一次平均分成5份,发现也多了一个,同样吃了这1个,并拿走其中一份.接着来的第3,第4,第5只猴子都是这样做的.......,根据上面的条件,问这5只猴子至少摘了多少个桃子?第5只猴子走后还剩下多少个桃子?算法分析:我们设总的桃子数为S0,五子猴子分得的桃子数分别为S1,S2,S3,S4,S5,则有以下关系式:S0 = 5*S1 + 1;4*S1 = 5*S2 + 1;4*S2 = 5*S3 + 1;4*S3 = 5*S4 + 1;4*S4 = 5*S5 + 1;我们可以枚举桃子总数S0,从5开始直到满足条件,此时S0的值就是最少的总桃子数。
对应程序如下:int main(void){int s[6] = {0};int i;for(s[0]=5; ;s[0]++){s[1] = s[0] - 1;if (s[1]%5) // (s[0] – 1)要能被5整除elses[1] /= 5;s[2] = 4 * s[1] - 1;if (s[2]%5) // (4 * s[1] - 1)要能被5整除continue;elses[2] /= 5;s[3] = 4 * s[2] - 1;if (s[3]%5)continue;elses[3] /= 5;s[4] = 4 * s[3] - 1;if (s[4]%5)continue;elses[4] /= 5;s[5] = 4 * s[4] - 1;if (s[5]%5)continue;elses[5] /= 5;break; //很关键,什么时候结束枚举}printf("摘了%d个桃子, 剩下%d个桃子\n", s[0], s[5]*4);for (i=0; i<6; i++)printf("%d ", s[i]);return 0;}程序输出:摘了3121个桃子, 剩下765个桃子。
根据程序结果我们知道循环体执行了3116次,同时我们可以知道第5个猴子分得255个桃子,所以如果枚举S5,则循环体只需执行了255次。
对应程序如下:#include <stdio.h>int main(void){int s[6] = {0};int i;for(s[5]=1; ;s[5]++){s[4] = 5 * s[5] + 1;if (s[4]%4)elses[4] /= 4;s[3] = 5 * s[4] + 1;if (s[3]%4)continue;elses[3] /= 4;s[2] = 5 * s[3] + 1;if (s[2]%4)continue;elses[2] /= 4;s[1] = 5 * s[2] + 1;if (s[1]%4)continue;elses[1] /= 4;s[0] = 5 * s[1] + 1;break;}printf("摘了%d个桃子, 剩下%d个桃子\n", s[0], s[5]*4);return 0;}我们可以发现求S4,S3,S2,S1的表达式完全是一样的,所以我们可以用一个函数或者循环来表示,改进后的程序如下:#include <stdio.h>int main(void){int s[6] = {0};int i;for(s[5]=1; ;s[5]++){for (i=4; i>0; i--){s[i] = 5 * s[i+1] + 1;if (s[i]%4)break;elses[i] /= 4;}if (i == 0){s[0] = 5 * s[1] + 1;break;}}printf("摘了%d个桃子, 剩下%d个桃子\n", s[0], s[5]*4);return 0;}2.如何确定枚举范围?例4:分数拆分问题(输入正整数k,找到所有的正整数x≥y,使得1/k=1/x+1/y。
)分析:由于x≥y,有1/x≤1/y,因此1/k-1/y≤1/y,即y≤2k。
这样只需要在2k范围内枚举y,然后根据y尝试计算出x即可。
3.约束条件的确定在枚举法解题中,判定条件的确定也是很重要的,如果约束条件不对或者不全面,就穷举不出正确的结果,我们再看看下面的例子。
例3:高斯日记。
计算1777年4月30日(高斯出生日)之后第8113天的日期是多少。
例4:大小之差。
由6个数字(允许重复)组成的最大6位数与最小6位数之间的差值也是一个6位数,且刚好包含了这6个数字。
(2014第五届蓝桥杯校内赛C语言B组)综合举例1:古堡算式(ABCDE * ?= EDCBA)(1)枚举对象,可以有两种选择:a)对每一个字符进行0~9的枚举;b)利用一个5位数进行10000~99999的枚举;(2)枚举范围设定对于用5位数来枚举的方式,根据条件“各字符均不相同”、以及乘上一个1位数后仍然是5位数的情况,可缩小枚举范围为12345~49876。
(3)约束条件,根据题目可知有两个约束条件:a)各字符均不相同(即:A!=B && A!=C && A!=D && A!=E && B!=C && B!=D && B!=E && C!=D && C!=E && D!=E)b)算式(即ABCDE * ?== EDCBA)下面分别按上述两种枚举对象给出程序代码:方法一:#include<stdio.h>int x[5]; //用于存放5个字符对应的5个数字void calc(int &a, int &b) // 计算5位数的值{int i;a=b=0;for (i=0; i<5; i++){a = 10 * a + x[i];b = 10 * b + x[5-i-1];}return;}int main(int argc, char* argv[]){int flag[10]={0}, a=0, b=0, t; //flag数组用于表示各数字是否被选用for (x[0]=0; x[0]<=9; x[0]++){flag[x[0]] = 1;for (x[1]=0; x[1]<=9; x[1]++)if (!flag[x[1]]){flag[x[1]] = 1;for (x[2]=0; x[2]<=9; x[2]++)if (!flag[x[2]]){flag[x[2]] = 1;for (x[3]=0; x[3]<=9; x[3]++)if (!flag[x[3]]){flag[x[3]] = 0;for (x[4]=0; x[4]<=9; x[4]++)if (!flag[x[4]]){calc(a,b);for (t=2; t<=9; t++)if (a*t==b) //约束条件printf("A=%d\nB=%d\nC=%d\nD=%d\nE=%d\n?=%d\n", x[0],x[1],x[2],x[3],x[4],t);}flag[x[3]] = 0;}flag[x[2]] = 0;}flag[x[1]] = 0;}flag[x[0]] = 0;}return 0;}方法二:int main(int argc, char* argv[]){int A,B,C,D,E,t,x,y;for (x=12345; x<=49876; x++){A = x/10000;B = (x%10000)/1000;C = (x%1000)/100;D = (x%100)/10;E = x % 10;if (A!=B && A!=C && A!=D && A!=E && B!=C && B!=D && B!=E && C!=D && C!=E && D!=E ){y = E*10000+D*1000+C*100+B*10+A;for (t=2; t<=9; t++)if (x * t==y)printf(“A=%d\nB=%d\nC=%d\nD=%d\nE=%d\n?=%d\n",A,B,C,D,E,t);}}return 0;}综合举例2:警察抓住A B C D四名罪犯,其中一人是小偷。