递推.docx

上传人:b****6 文档编号:7570350 上传时间:2023-01-25 格式:DOCX 页数:11 大小:102KB
下载 相关 举报
递推.docx_第1页
第1页 / 共11页
递推.docx_第2页
第2页 / 共11页
递推.docx_第3页
第3页 / 共11页
递推.docx_第4页
第4页 / 共11页
递推.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

递推.docx

《递推.docx》由会员分享,可在线阅读,更多相关《递推.docx(11页珍藏版)》请在冰豆网上搜索。

递推.docx

递推

算法——递推算法

递推算法

给定一个数的序列H0,H1,…,Hn,…若存在整数n0,使当n>n0时,可以用等号(或大于号、小于号)将Hn与其前面的某些项Hi(0

递推算法是一种简单的算法,即通过已知条件,利用特定关系得出中间推论,直至得到结果的算法。

递推算法分为顺推和逆推两种。

相对于递归算法,递推算法免除了数据进出栈的过程,也就是说,不需要函数不断的向边界值靠拢,而直接从边界出发,直到求出函数值.

比如阶乘函数:

f(n)=n*f(n-1)

在f(3)的运算过程中,递归的数据流动过程如下:

f(3){f(i)=f(i-1)*i}-->f

(2)-->f

(1)-->f(0){f(0)=1}-->f

(1)-->f

(2)--f(3){f(3)=6}

而递推如下:

f(0)-->f

(1)-->f

(2)-->f(3)

由此可见,递推的效率要高一些,在可能的情况下应尽量使用递推.但是递归作为比较基础的算法,它的作用不能忽视.所以,在把握这两种算法的时候应该特别注意。

顺推法

所谓顺推法是从已知条件出发,逐步推算出要解决的问题的方法叫顺推。

如斐波拉契数列,设它的函数为f(n),已知f

(1)=1,f

(2)=1;f(n)=f(n-2)+f(n-1)(n>=3,n∈N)。

则我们通过顺推可以知道,f(3)=f

(1)+f

(2)=2,f(4)=f

(2)+f(3)=3……直至我们要求的解。

逆推法

所谓逆推法从已知问题的结果出发,用迭代表达式逐步推算出问题的开始的条件,即顺推法的逆过程,称为逆推。

递推算法的经典例子

【案例】从原点出发,一步只能向右走、向上走或向左走。

恰好走N步且不经过已走的点共有多少种走法?

样例输入:

N=2

样例输出:

result=7

样例输入:

N=3

样例输出:

result=17

解题思路:

要解决走N步共有多少种走法,我们在拿到题目的时候最直接的想法就是先画出当N=1、N=2、N=3。

N=n时对应走法的图例,由简单到复杂、由特殊到一般的推理过程,找出规律获得解题的思路。

在数学上,我们称为归纳法。

如果用编程的方法来求解这样的推理题,我们把这样的求解思路(算法)称之为递推法。

递推的精髓在于f(n)的结果一般由f(n-1)、f(n-2)…..f(n-k)的前k次结果推导出来。

我们在解决这类递推问题时,难点就是如何从简单而特殊的案例,找到问题的一般规律,写出f(n)与f(n-1)、f(n-2)…..f(n-k)之间的关系表达式,从而得出求解的结果。

在历年noip的复赛当中,参赛选手对于这类题目都有这样的感受,往往花费了大量的时间来分析题目的一般规律,写出f(n)的一般表达式,而编程实现可能只需要几分钟的时间。

所以我们在平时训练的时候,对于这样的递推题目,就必须掌握如何分析问题,从特殊推导出一般的规律,写出想要的关系表达式,问题就迎刃而解了。

下面是这道题解题的心得,供大家参考:

(1)当N=1时,绘出走法图

(图1)共有3种不同的走法,也就是黑色线条的数量,即f

(1)=3

(2)当N=2时,绘出走法图

(图2)共有7种不同的走法,也就是绿色线条的数量,即f

(2)=7

(3)当N=3时,绘出走法图

(图3)共有17种不同的走法,也就是红色线条的数量,即f(3)=17

由此,我们不难看出,对于任何一个起点,最多可以走出3种走法,但最少必须走出2种走法。

那么我们要求出f(n),实际上转换为如果我们能够得到上一步即f(n-1)有多少个终点是有3种走法的,有多少个点有2种走法的,那么问题就解决了。

a.上一步,即f(n-1)有多少个终点是有3种走法的。

      对于N=3时,f(n-1)=f

(2),有3个点A、B、C可以走出3种不同走法的,这3个点是怎么得到的呢?

它的存在与N值有没有必然的联系?

如果我们能找到它与N之间的关系,问题也就解决了。

有了这样的思路以后,我们不难找到这样的规律:

如果f(n-2)存在,即上上步存在,那么从上上步出发的线路里面必然会有一条向上走的线路,而这条向上走的线路在到达f(n-1)之后, 向f(n)出发时也必然有左、上、右这三种走法,那么我们就得出了这样的结论:

当f(n-2)存在时,f(n-2)的值实际上就等价于f(n-1)有多少个终点是有3种走法。

        b.   f(n-1)有多少个终点是有2种走法的

对于N=3时,有4个点D、E、F、G可以走出2种不同走法的,这4个点又是怎么得到的呢?

它与N值有什么联系呢?

实际上我们在解决了上一个问题的时候,这个问题就变得相当容易了,f(n-1)减掉刚才有3种走法的点,剩下的点不就是只有2种走法了吗?

即f(n-1)-f(n-2)。

   c.得出f(n)的一般关系式

f(n)=3*f(n-2)+2*(f(n-1)-f(n-2))(n>=3)

化简:

f(n)=2*f(n-1)+f(n-2)(n>=3)

     有一点需要补充的就是,任何递推题,都会有临界条件。

当N=1时,f(n)=3;,当N=2时,f(n)=7,这些都可以看成是临界条件。

只有当N>=3时,即上上步存在的情况下,就可以得出f(n)的一般通式:

f(n)=2*f(n-1)+f(n-2)

         (本题还有其他的解法,同学们可以继续挖掘!

【参考程序】

#include

#include

intmain()

{

  intn;

  inti;

  intfn_1,fn_2;

  printf("pleaseinputn=");

  scanf("%d",&n);//输入任意n值

  intfn=0;

  if(n==1)

    fn=3;//初始化当n=1和n=2时的临界条件

  elseif(n==2)

    fn=7;

  else{

    fn_1=7;

    fn_2=3;

    for(i=3;i<=n;i++)

    {

       fn=2*fn_1+fn_2;//当n>=3时fn的通式

       fn_2=fn_1;//更新fn_1和fn_2的值

       fn_1=fn;

    }

  }

  printf("一共有%d种走法!

\n",fn); //输出结果

  return0;

}

阿牛的EOF牛肉串

ProblemDescription

今年的ACM暑期集训队一共有18人,分为6支队伍。

其中有一个叫做EOF的队伍,由04级的阿牛、XC以及05级的COY组成。

在共同的集训生活中,大家建立了深厚的友谊,阿牛准备做点什么来纪念这段激情燃烧的岁月,想了一想,阿牛从家里拿来了一块上等的牛肉干,准备在上面刻下一个长度为n的只由"E""O""F"三种字符组成的字符串(可以只有其中一种或两种字符,但绝对不能有其他字符),阿牛同时禁止在串中出现O相邻的情况,他认为,"OO"看起来就像发怒的眼睛,效果不好。

你,NEWACMer,EOF的崇拜者,能帮阿牛算一下一共有多少种满足要求的不同的字符串吗?

PS:

阿牛还有一个小秘密,就是准备把这个刻有EOF的牛肉干,作为神秘礼物献给杭电五十周年校庆,可以想象,当校长接过这块牛肉干的时候该有多高兴!

这里,请允许我代表杭电的ACMer向阿牛表示感谢!

再次感谢!

 

Input

输入数据包含多个测试实例,每个测试实例占一行,由一个整数n组成,(0

 

Output

对于每个测试实例,请输出全部的满足要求的涂法,每个实例的输出占一行。

 

SampleInput

1

2

 

SampleOutput

3

8

设n位字符串,最后一位是O的字符串的个数为a[n],最后一位不是O的字符串的个数是b[n],

总字符串个数为x[n],

则有

x[n]=a[n]+b[n];

a[n]=b[n-1];

b[n]=2*x[n-1];

====>x[n]=2*x[n-1]+2*x[n-2]

#include

__int64x[40]={0,3,8};

intmain(){

intn;

for(n=3;n!

=40;++n)

x[n]=2*(x[n-1]+x[n-2]);

while(scanf("%d",&n)==1)

printf("%I64d\n",x[n]);

return0;

}

不容易系列之(4)——考新郎

 

ProblemDescription

国庆期间,省城HZ刚刚举行了一场盛大的集体婚礼,为了使婚礼进行的丰富一些,司仪临时想出了有一个有意思的节目,叫做"考新郎",具体的操作是这样的:

首先,给每位新娘打扮得几乎一模一样,并盖上大大的红盖头随机坐成一排;

然后,让各位新郎寻找自己的新娘.每人只准找一个,并且不允许多人找一个.

最后,揭开盖头,如果找错了对象就要当众跪搓衣板...

看来做新郎也不是容易的事情...

假设一共有N对新婚夫妇,其中有M个新郎找错了新娘,求发生这种情况一共有多少种可能.

 

Input

输入数据的第一行是一个整数C,表示测试实例的个数,然后是C行数据,每行包含两个整数N和M(1

 

Output

对于每个测试实例,请输出一共有多少种发生这种情况的可能,每个实例的输出占一行。

 

SampleInput

2

22

32

 

SampleOutput

1

3

错排+组合数

错排公式:

a[i]=(i-1)*(a[i-1]+a[i-2]);   然后乘以从m个中挑出t个的排列组合

#include

intmain()

{

inta,n,m,i;

__int64p;

__int64q;

__int64cuopai[22]={0,0,1,2};

for(i=4;i<22;i++)

{

cuopai[i]=(i-1)*(cuopai[i-1]+cuopai[i-2]);

}

scanf("%d",&a);

while(a--)

{

scanf("%d%d",&n,&m);

p=1;q=1;

for(i=n;i>n-m;i--)

p*=i;

for(i=m;i>1;i--)

q*=i;

printf("%I64d\n",p/q*cuopai[m]);

}

return0;

}

折线分割平面

ProblemDescription

我们看到过很多直线分割平面的题目,今天的这个题目稍微有些变化,我们要求的是n条折线分割平面的最大数目。

比如,一条折线可以将平面分成两部分,两条折线最多可以将平面分成7部分,具体如下所示。

Input

输入数据的第一行是一个整数C,表示测试实例的个数,然后是C行数据,每行包含一个整数n(0

Output

对于每个测试实例,请输出平面的最大分割数,每个实例的输出占一行。

SampleInput

2

1

2

SampleOutput

2

7

Author

lcy

Source

对n取任意值时,分割平面数=交点数+顶点数+1,我们假设f(n-1)已知,又f(n)每一条拆线与另一条拆线交点为4,则新加第N条拆线交点数增加4*(n-1)

顶点数比f(n-1)多一个,故f(n)=f(n-1)+4*(n-1)+1

分析:

先看N条相交的直线最多能把平面分割成多少块

当添加第N条只显示,为了使平面最多,则第N条直线要与前面的N-1条直线都相交,且没有任何三条直线教育一个点。

则第N条直线有N-1个交点。

由于每增加N个交点,就增加N+1个平面,所以用N条直线来分隔平面,最多的数是1+1+2+3+…+n=1+n*(n+1)/2;

 

再看每次增加两条相互平行的直线

  

 

当第N次添加时,前面已经有2N-2条直线了,所以第N次添加时,第2N-1条直线和第2N条直线都各能增加2*(n-1)+1个平面。

所以第N次添加增加的面数是2[2(n-1)+1]=4n-2个。

因此,总面数应该是

1+4n(n+1)/2-2n=2n2+1 

 

如果把每次加进来的平行边让它们一头相交

则平面1、3已经合为一个面,因此,每一组平行线相交后,就会较少一个面,

所以所求就是平行线分割平面数减去N,为2n2-n+1

利用上述总结公式f(n)=2n2-n+1

#include

intmain()

{

intT,n;

scanf("%d",&T);

while(T--&&scanf("%d",&n)!

=EOF)

printf("%d\n",2*n*n-n+1);

return0;

}

或者利用公式f(n)=f(n-1)+4*(n-1)+1

#include

intmain()

{

__int64s[10001];

inti,T,n;

scanf("%d",&T);

while(T--)

{

s[0]=1;

scanf("%d",&n);

for(i=1;i<=n;i++)

s[i]=s[i-1]+4*(i-1)+1;

printf("%I64d\n",s[i-1]);

}

return0;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 面试

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

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