1、【样例】 trave1.in trave1.out abc 1 bca【算法分析】在肯定有解的情况下,上述算法最终可以递归调用到0、1个结点,如果有多组解,那么调用到两个结点时,如先序为ab、后序为ba,此时有可能有如下两种结构:a a / b b 这两种结构的中序遍历结果分别为:ba、ab,有两种。 根据分步相乘的原理,对比两个字符串,每出现一次如上的情况,可能有的结构数目(结构不同,中序遍历结果也不同,因此可能有的二叉树结构的数目就是可能有的中序遍历结果数目)就乘以2一次,最终得到总的数目。这也可以理解为一种递推的方法。从这里可以看到,在肯定有解的情况下,给定先序遍历的结果和后序遍历的结果
2、,可能有2n种可能的结构,也就是中序遍历可能得到2n种不同的结果,其中n0。那么这里的n最大可能是多少呢?可以证明n的最大值为字符串的长度加1整除2。【参考程序】program fgdjfk;var i,j,m,sum:longint; s1,s2:string;beginassign(input,travel.in);reset(input);assign(output,travel.outrewrite(output); readln(s1); readln(s2); sum:=1; for i:=1 to length(s1)-1 do begin m:=pos(s1i,s2); if
3、m1 then if s1i+1=s2m-1 then=sum*2; end; writeln(sum);close(input);close(output);end.2 产生数 源程序名 build.?可执行文件名 build.exe输入文件名 build.in输出文件名 build.out 给出一个整数n(n1030)和m个变换规则(m20)。 约定:一个数字可以变换成另一个数字,规则的右部不能为零,即零不能由另一个数字变换而成。而这里所说的一个数字就是指一个一位数。 现在给出一个整数n和m个规则,要你求出对n的每一位数字经过任意次的变换(0次或多次),能产生出多少个不同的整数。 共m+2
4、行,第一行是一个不超过30位的整数n,第2行是一个正整数m,接下来的m行是m个变换规则,每一规则是两个数字x、y,中间用一个空格间隔,表示x可以变换成y。 仅一行,表示可以产生的不同整数的个数。 build.in build.out 123 6 2 1 2 2 3 如果本题用搜索,搜索的范围会很大(因为n可能有30位!),显然无法在规定的时间内出解。而我们注意到本题只需计数而不需要求出具体方案,所以我们稍加分析就会发现,可以用乘法原理直接进行计数。 设Fi表示从数字i出发可以变换成的数字个数(这里的变换可以是直接变换,也可以是间接变换,比如样例中的1可以变换成2,而2又可以变换成3,所以1也可
5、以变换成3;另外自己本身不变换也是一种情况)。那么对于一个长度为m位的整数a,根据乘法原理,能产生的不同的整数的个数为:Fa1*Fa2*Fa3*Fam。 下面的问题是如何求Fi呢?由于这些变换规则都是反映的数字与数字之间的关系,所以定义一个布尔型的二维数组g0.9,0.9来表示每对数字之间是否可以变换,初始时都为False;根据输入的数据,如果数字i能直接变换成数字j,那么gi,j置为True,这是通过一次变换就能得到的;接下来考虑那些间接变换可得到的数字对,很明显:如果i可以变为k,k又可以变为j,那么i就可以变为j,即: for k:=0 to 9 do for j: gi,jgi,jor
6、(gi,k and gk,j); 最后还要注意,当n很大时,解的个数很大,所以要用高精度运算。program drgjol;var i,j,k,n,m,l: a:array1.30of longint;/读入的数 f:array0.9of longint;/i对应的变换数目 g:array0.9,0.9of boolean;/变换规则array1.1000of longint;/储存答案 ch:char;procedure mul(k:longint);/计算sumvar i,x: x:=0;=1 to l do sumi:=sumi*k+x;=sumi div 10;=sumi mod 10
7、; while x0 do inc(l); suml:=x mod 10;=x div 10;end;mulbuild.inbuild.out n: fillchar(g,sizeof(g),false); while not seekeoln do inc(n); read(ch); an:=ord(ch)-ord(0 readln(m);=1 to m do readln(j,k); gj,k:=true; gi,j:=gi,jor(gi,k and gk,j);/计算变换规则 fillchar(f,sizeof(f),0);=0 to 9 do gi,i: if gi,j then in
8、c(fi);/统计数目 sum1: l:=1 to n do/求sum mul(fai);=l downto 1 do/输出 write(sumi); writeln;3 出栈序列统计源程序名 stack.?可执行文件名 stack.exe输入文件名 stack.in输出文件名 stack.out 栈是常用的一种数据结构,有n个元素在栈顶端一侧等待进栈,栈顶端另一侧是出栈序列。你已经知道栈的操作有两种:push和pop,前者是将一个元素进栈,后者是将栈顶元素弹出。现在要使用这两种操作,由一个操作序列可以得到一系列的输出序列。请你编程求出对于给定的n,计算并输出由操作数序列1,2,n,经过一系列
9、操作可能得到的输出序列总数。【输入】 【输出】 就一个数n(1n1000)。 一个数,即可能输出序列的总数目。 stack.in stack.out 3 5 在第一章练习里,我们通过回溯的方法计算并输出不同的出栈序列,这里只要求输出不同的出栈序列总数目,所以我们希望能找出相应的递推公式进行处理。 从排列组合的数学知识可以对此类问题加以解决。 我们先对n个元素在出栈前可能的位置进行分析,它们有n个等待进栈的位置,全部进栈后在栈里也占n个位置,也就是说n个元素在出栈前最多可能分布在2*n位置上。 出栈序列其实是从这2n个位置上选择n个位置进行组合,根据组合的原理,从2n个位置选n个,有C(2n,n
10、)个。但是这里不同的是有许多情况是重复的,每次始终有n个连续的空位置,n个连续的空位置在2n个位置里有n+1种,所以重复了n+1次。所以出栈序列的种类数目为: C(2n,n)/(n+1)=2n*(2n-1)*(2n-2)*(n+1)/n!/(n+1)=2n*(2n-1)*(2n-2)*(n+2)/n!。 考虑到这个数据可能比较大,所以用高精度运算来计算这个结果。本题实际是一个经典的Catalan数模型。有关Catalan数的详细解释请参考组合数学等书。program dfgdjk;var i,j,n,m,l: p:array2.2000of boolean;/素数表array1.2000of longint; a,b,c:/素因子表procedure prime;/计算12000内的素数var i,j: fillchar(p,sizeof(p),true); i:=2; while i*i=2000 do j:=i+i; while j pj:=false;=j+i; inc(i);=2 to 2000 do if pi then inc(m); am:=i;prime/高精乘法求sum
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1