ImageVerifierCode 换一换
格式:DOCX , 页数:39 ,大小:33.29KB ,
资源ID:30664521      下载积分:10 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/30664521.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(acm搜索算法dfs排列组合.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

acm搜索算法dfs排列组合.docx

1、acm搜索算法dfs排列组合排列与组合(非递归的DFS算法) 组合的生成与排列相似,组合中数字相同顺序不同的可以归纳为一个组合,可以按升序生成或降序生成,即后面搜索到的数要大于(或小于)前面的数,我在这里以升序为例。#include void comb(int m,int n)int t,k,i,a20;k=1;t=0;a0=0;ak=0;while(k0) ak+; /向下搜索while(ak=m)&(ak=ak-1)ak+; /判断当前结点是不是可行的,若不是则在容许范围内继续搜索if(ak=m) /有没有超出范围if(k=n) /是不是目标解for(i=1;i=n;i+)printf(%

2、d,ai); t+; /输出完毕回溯到上一层,继续搜索其他解k-;printf(n);else /不是则进行下一层的搜索k+;ak=0;else k-; /若当前状态找不到可行的解则回溯printf(sum:%d,t);int main()int m,n;scanf(%d%d,&m,&n);comb(m,n); return 0; #include /组合using namespace std;int n1001, vtd1001, digits, nums;void dfs(int x, int crnt);int main()memset(n, 0, sizeof n);memset(vt

3、d, 0, sizeof vtd);cin nums digits;dfs(1, 1);return 0;void dfs(int x, int crnt)if(x = digits)for(int j = crnt; j = nums; j+)if(!vtdj)vtdj = 1;nx = j;dfs(x + 1, j);vtdj = 0; cout ni;cout endl;#include /排列using namespace std;int n, m;int vst11;int p11;void_read_()cin n m;void_outp_()for( int i = 1; i =

4、 m; i+ )cout pi;cout endl;void_dfs_( int x )if( x = m )for( int i = 1; i m )_outp_();intmain()_read_();_dfs_( 1 );return 0;前言 这篇论文主要针对排列组合对回溯算法展开讨论,在每一个讨论之后,还有相关的推荐题。在开始之前,我们先应该看一下回溯算法的概念,所谓回溯:就是搜索一棵状态树的过程,这个过程类似于图的深度优先搜索(DFS),在搜索的每一步(这里的每一步对应搜索树的第i层)中产生一个正确的解,然后在以后的每一步搜索过程中,都检查其前一步的记录,并且它将有条件的选择以后的

5、每一个搜索状态(即第i+1层的状态节点)。需掌握的基本算法:排列:就是从n个元素中同时取r个元素的排列,记做P(n,r)。(当r=n时,我们称P(n,n)=n!为全排列)例如我们有集合OR = 1,2,3,4,那么n = |OR| = 4,切规定r=3,那么P(4,3)就是:1,2,3; 1,2,4; 1,3,2; 1,3,4;1,4,2;1,4,3;2,1,3;2,1,4; 2,3,1; 2,3,4; 2,4,1; 2,4,3; 3,1,2; 3,1,4; 3,2,1; 3,2,4; 3,4,1; 3,4,2; 4,1,2; 4,1,3; 4,2,1; 4,2,3; 4,3,1; 4,3,2

6、算法如下:int n, r;char usedMaxN;int pMaxN;void permute(int pos) int i;/*如果已是第r个元素了,则可打印r个元素的排列 */if (pos=r) for (i=0; ir; i+)cout (pi+1);cout endl;return;for (i=0; in; i+)if (!usedi) /*如果第i个元素未用过*/*使用第i个元素,作上已用标记,目的是使以后该元素不可用*/usedi+;/*保存当前搜索到的第i个元素*/ppos = i;/*递归搜索*/permute(pos+1);/*恢复递归前的值,目的是使以后改元素可用

7、*/usedi-;相关问题UVA 524 Prime Ring Problem可重排列:就是从任意n个元素中,取r个可重复的元素的排列。例如,对于集合OR=1,1,2,2, n = |OR| = 4, r = 2,那么排列如下:1,1; 1,2; 1,2; 1,1; 1,2; 1,2; 2,1; 2,1; 2,2; 2,1; 2,1; 2,2则可重排列是:1,1; 1,2; 2,1; 2,2.算法如下:#define FREE -1int n, r;/*使元素有序*/int EMaxN = 0,0,1,1,1; int PMaxN;char usedMaxN;void permute(int

8、pos)int i;/*如果已选了r个元素了,则打印它们*/if (pos=r) for (i=0; ir; i+)cout Pi;cout endl;return;/*标记下我们排列中的以前的元素表明是不存在的*/Ppos = FREE;for (i=0; in; i+)/*如果第I个元素没有用过,并且与先前的不同*/if (!usedi & Ei!=Ppos) /*使用这个元素*/usedi+;/*选择现在元素的位置*/Ppos = Ei;/*递归搜索*/permute(pos+1);/*恢复递归前的值*/usedi-;相关习题UVA 10098 Generating Fast, Sort

9、ed Permutations组合:从n个不同元素中取r个不重复的元素组成一个子集,而不考虑其元素的顺序,称为从n个中取r个的无重组合,例如OR = 1,2,3,4, n = 4, r = 3则无重组合为:1,2,3; 1,2,4; 1,3,4; 2,3,4.算法如下:int n, r;int C5;char used5;void combine(int pos, int h)int i;/*如果已选了r个元素了,则打印它们*/if (pos=r) for (i=0; ir; i+)cout Ci;cout endl;return;for (i=h; i=n-r+pos; i+) /*对于所有

10、未用的元素*/if (!usedi) /*把它放置在组合中*/Cpos = i;/*使用该元素*/usedi+;/*搜索第i+1个元素*/combine(pos+1,i+1);/*恢复递归前的值*/usedi-;相关问题:Ural 1034 Queens in peaceful position可重组合:类似于可重排列。例 给出空间中给定n(n10)个点,画一条简单路径,包括所有的点,使得路径最短。解:这是一个旅行售货员问题TSP。这是一个NP问题,其实就是一个排列选取问题。算法如下:int n, r;char usedMaxN;int pMaxN;double min;void permut

11、e(int pos, double dist)int i;if (pos=n) if (dist min) min = dist;return;for (i=0; in; i+)if (!usedi) usedi+;ppos = i;if (dist + cost(pointppos-1, pointppos) min)permute(pos+1, dist + cost(pointppos-1, pointppos);usedi-;例对于0和1的所有排列,从中同时选取r个元素使得0和1的数量不同。解 这道题很简单,其实就是从0到2r的二元表示。算法如下:void dfs(int pos)if

12、 (pos = r)for (i=0; ir; i+) coutpi;coutendl;return;ppos = 0;dfs(pos+1);ppos = 1;dfs(pos+1);相关问题:Ural1005 Stone pile1060 Flip Game1152 The False Mirrors例找最大团问题。一个图的团,就是包括了图的所有点的子图,并且是连通的。也就是说,一个子图包含了n个顶点和n*(n-1)/2条边,找最大团问题是一个NP问题。算法如下:#define MaxN 50int n, max;int pathMaxNMaxN;int inCliqueMaxN;void d

13、fs(int inGraph)int i, j;int GraphMaxN;if ( inClique0+inGraph0max ) max=inClique0;/*对于图中的所有点*/for (i=1; i=inGraph0; i+)/*把节点放置到团中*/+inClique0;inCliqueinClique0=inGraphi;/*生成一个新的子图*/Graph0=0;for (j=i+1; jn;while (n 0)for (i=0; in; i+)for (j=0; jpathij;max = 1;/*初始化*/inClique0= 0;inGraph0 = n;for (i=0;

14、 in; i+) inGraphi+1=i;dfs(inGraph);coutmaxn;return 0;尽管排列组合是生活中经常遇到的问题,可在程序设计时,不深入思考或者经验不足都让人无从下手。由于排列组合问题总是先取组合再排列,并且单纯的排列问题 相对简单,所以本文仅对组合问题的实现进行详细讨论。以在n个数中选取m(0m=m0。/ b1.M用来存储当前组合中的元素(这里存储的是元素下标),/ 常量M表示满足条件的一个组合中元素的个数,M=m,这两个参数仅用来输出结果。void combine( int a, int n, int m, int b, const int M ) for(in

15、t i=n; i=m; i-) / 注意这里的循环范围bm-1 = i - 1;if (m 1)combine(a,i-1,m-1,b,M);else / m = 1, 输出一个组合 for(int j=M-1; j=0; j-)cout abj ;cout endl;因为递归程序均可以通过引入栈,用回溯转化为相应的非递归程序,所以组合问题又可以用回溯的方法来解决。为了便于理解,我们可以把组合问题化归为图 的路径遍历问题,在n个数中选取m个数的所有组合,相当于在一个这样的图中(下面以从1,2,3,4中任选3个数为例说明)求从1,1位置出发到达 m,x(m=x n ? n : m;int* or

16、der = new intm+1; for(int i=0; i=m; i+)orderi = i-1; / 注意这里order0=-1用来作为循环判断标识int count = 0; int k = m;bool flag = true; / 标志找到一个有效组合while(order0 = -1)if(flag) / 输出符合要求的组合 for(i=1; i=m; i+) cout aorderi ;cout endl;count+;flag = false;orderk+; / 在当前位置选择新的数字if(orderk = n) / 当前位置已无数字可选,回溯orderk- = 0;co

17、ntinue; if(k m) / 更新当前位置的下一位置的数字 order+k = orderk-1;continue;if(k = m)flag = true;delete order;return count;下面是测试以上函数的程序:int main()const int N = 4;const int M = 3;int aN;for(int i=0;iN;i+)ai = i+1;/ 回溯方法cout combine(a,N,3) endl; / 递归方法int bM;combine(a,N,M,b,M); return 0;由上述分析可知,解决组合问题的通用算法不外乎递归和回溯两种

18、。在针对具体问题的时候,因为递归程序在递归层数上的限制,对于大型组合问题而言,递归不是一个好的选择,这种情况下只能采取回溯的方法来解决。n个数的全排列问题相对简单,可以通过交换位置按序枚举来实现。STL提供了求某个序列下一个排列的算法next_permutation,其算法原理如下:1. 从当前序列最尾端开始往前寻找两个相邻元素,令前面一个元素为*i,后一个元素为*ii,且满足*i*ii;2. 再次从当前序列末端开始向前扫描,找出第一个大于*i的元素,令为*j(j可能等于ii),将i,j元素对调;3. 将ii之后(含ii)的所有元素颠倒次序,这样所得的排列即为当前序列的下一个排列。其实现代码如

19、下:template bool next_permutation(BidirectionalIterator first, BidirectionalIterator last) if (first = last) return false; / 空範圍BidirectionalIterator i = first;+i;if (i = last) return false; / 只有一個元素i = last; / i 指向尾端-i;for(;) BidirectionalIterator ii = i;-i;/ 以上,鎖定一組(兩個)相鄰元素if (*i *ii) / 如果前一個元素小於後一

20、個元素 BidirectionalIterator j = last; / 令 j指向尾端while (!(*i *-j); / 由尾端往前找,直到遇上比 *i 大的元素iter_swap(i, j); / 交換 i, jreverse(ii, last); / 將 ii 之後的元素全部逆向重排return true;if (i = first) / 進行至最前面了 reverse(first, last); / 全部逆向重排return false; 下面程序演示了利用next_permutation来求取某个序列全排列的方法:int main()int ia = 1,2,3,4;vecto

21、r iv(ia,ia+sizeof(ia)/sizeof(int);copy(iv.begin(),iv.end(),ostream_iterator(cout, );cout endl;while(next_permutation(iv.begin(),iv.end()copy(iv.begin(),iv.end(),ostream_iterator(cout, );cout endl;return 0;注意:上面程序中初始序列是按数值的从小到大的顺序排列的,如果初始序列无序的话,上面程序只能求出从当前序列开始的后续部分排列,也就是说next_permutation求出的排列是按排列从小到大

22、的顺序进行的。1。最近一直在考虑从m个数里面取n个数的算法。最容易理解的就是递归,但是其效率,实在不能使用。一直找寻中,今日得果2。算法来源与互联网组合算法 本程序的思路是开一个数组,其下标表示1到m个数,数组元素的值为1表示其下标 代表的数被选中,为0则没选中。 首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。 然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为 “01”组合,同时将其左边的所有“1”全部移动到数组的最左端。 当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得 到了最后一个组合。 例如求5中选3的组合: 1 1 1

23、 0 0 /1,2,3 1 1 0 1 0 /1,2,4 1 0 1 1 0 /1,3,4 0 1 1 1 0 /2,3,4 1 1 0 0 1 /1,2,5 1 0 1 0 1 /1,3,5 0 1 1 0 1 /2,3,5 1 0 0 1 1 /1,4,5 0 1 0 1 1 /2,4,5 0 0 1 1 1 /3,4,5 全排列算法 从1到N,输出全排列,共N!条。 分析:用N进制的方法吧。设一个N个单元的数组,对第一个单元做加一操作,满N进 一。每加一次一就判断一下各位数组单元有无重复,有则再转回去做加一操作,没 有则说明得到了一个排列方案。/递归算法全排列是将一组数按一定顺序进行排列

24、,如果这组数有n个,那么全排列数为n!个。现以1, 2, 3, 4, 5为例说明如何编写全排列的递归算法。1、首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。由于一个数的全排列就是其本身,从而得到以上结果。2、再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六组数。即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合.从而可以推断,设一组数p = r1, r2, r3, . ,rn, 全排列为perm(p),pn = p - rn。因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), . , rnperm(pn)。当n = 1时perm(p = r1。为了更容易理解,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1