oj递归-回顾

1.逆波兰表达式
一种把运算符前置的算数表达式(特点运算符之间不必有优先级关系)

#include <iostream>
#include <cstdio>
using namespace std;
float atof(char *c)
{
    float d;
    sscanf(c,"%f",&d);     //将字符转化为对应的整数;
    return d;
}
double ys()
{
    char a[10];
    scanf("%s" ,a);         //输入字符串a;
    switch (a[0])           //遇到运算符返回后两个进行运算;
    {
        case '+': return ys()+ys();
        case '-': return ys()-ys();
        case '*': return ys()*ys();
        case '/': return ys()/ys();
        default: return atof(a);
    }
}
int main()
{
    double sum;
    sum=ys();                //调用函数
    printf("%.6f" ,sum);    //输出保留小数点后6位的数;
    return 0;
}

小结:首先递归的终止是读取终止符,其次是递归的方式是遇到运算符返回后两位进行运算,最后<stdio.h>中的sscanf函数:从字符串中读进与指定格式相符的数据。

2.全排序:输出给定字符串的所有全排序,并已知给定的是从小到大排序的。

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
string str[722];            //全局变量;
int a=0;                     
void pe(char *l,int k, int m)
{
    if(k==m)
        {
            str[a]=l;
            a++;
        }
    else
      for(int j=k;j<=m;j++)
          {
              swap(l[k],l[j]);   //交换函数;
              pe(l,k+1,m);
              swap(l[k],l[j]);
          }
}
int main()
{
    char l[10];
    int m;
    scanf("%s",l);
    m=strlen(l);              //读取给定字符串的长度;
    
    pe(l,0,m-1);
    sort(str,str+a);          //将所得的结果进行从小到大排序;
    for(int i=0;i<a;i++)
        cout<<str[i]<<endl;
    return 0;
}

总结:首先递归思想一串字符串进行排序,首先定一个在头部然后后面在进行排序,递归每定一个排的方式减少,但只剩最后一个字符就只有一种排法,为递归的终止条件。运用swap函数,中的strlen函数:计算给定字符串的(unsigned int)长度,sort函数:排序函数,默认从小到大。

3.Pell数列:a1=1,a2=2,…an=2*a(n-1)+a(n-2).求pell数列的第K项模上32767是多少。

#include <iostream>
#define m 1000005         //宏定义命令;
using namespace std;
long long a[m]={0};
long long fbnq(int n)
{
    if(a[n]!=0)                                       //记忆化递归;
        return a[n];
    if(n==1) return 1;
    if(n==2) return 2;
    else return a[n]=(fbnq(n-1)*2+fbnq(n-2))%32767;   //给定递归的规则;
}
int main()
{
    long long n,i;
    cin>>n;
    long long b[n],c[n];
    for(i=0;i<n;i++)
        {
            cin>>b[i];
            c[i]=fbnq(b[i]);
        }
    for(i=0;i<n;i++)
        {
            cout<<c[i]<<endl;
        }
    return 0;
}

总结:首先题目给出咯递归规则(an=z*a(n-1)+a(n-2)),但直接用递归会超时,所以得将递归记忆化

4.爬楼梯:每次可以走1级或者2级,输入楼梯的级数,求不同的走法数。

#include <iostream>
#include <stdio.h>
using namespace std;
int zf(int n)
{
    if(n>2)
        return zf(n-1)+zf(n-2);   //递归调用;
    else return n;
}

int main()
{
    int n=0,b[30],c[30];
    while(cin>>b[n])
        n++;
    for(int i=0;i<n;i++)
        c[i]=zf(b[i]);
    for(int j=0;j<n;j++)
        cout<<c[j]<<endl;
    return 0;
}

总结:递归的规则递归的规则,总共的方法等于每次走一梯,加上每次走两梯的方法,即f(n)=f(n-1)+f(n-2).此题的关键就在于找这递归规则。

5.放苹果:把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?

#include <iostream>
using namespace std;
int f(int m,int n)
{
    if(n==0) return 0;
    if(m==0||n==1)        //递归的终止条件就m=0或n=1;
        return 1;
    else if(m>=n)
            return f(m-n,n)+f(m,n-1);   //递归即返回每个盘子都放的方法加上有盘子为空盘的方法;
         else return f(m,m);
}
int main()
{
    int t,i,m,n,b[20];
    cin>>t;
    for(i=0;i<t;i++)
        {
            cin>>m>>n;
            b[i]=f(m,n);
        }
    for(i=0;i<t;i++)
        cout<<b[i]<<endl;
    return 0;
}

总结:递归的终止条件为苹果为零时或盘子数为1时,递归终止;递归规则,总数为每个盘子都放有苹果的总数(f(m-n,n))加上有空盘子的情况下的总数(f(m,n-1))。

6.分解因数:给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * … * an,并且1 < a1 <= a2 <= a3 <= … <= an,问这样的分解的种数有多少。注意到a = a也是一种分解。

#include<iostream>
using namespace std;

int fy(int m,int n)
{                
    int a=1;                    //为本身的那种情况;
    if(n==1) return 0;          //递归终止条件;
    for(int i=m;i*i<=n;i++)     //从2开始遍历找所有的能分解的情况;
        if(n%i==0)
            {
                a=a+fy(i,n/i);  //递归返回找更大的因数;
            }
    return a;
}
int main()
{
    int n;
    cin>>n;
    int b[n],c[n];
    for(int i=0;i<n;i++)
        {
            cin>>b[i];
            c[i]=fy(2,b[i]);
        }
    for(int j=0;j<n;j++)
        cout<<c[j]<<endl;
}

总结:主要是递归规则的寻找,从最小的2开始,一一找出所有的因数。较大的因数还可分解为更小的因数的存在,当为全为最小的因数组时为最后一种情况。

7.2的幂次方表示:任何一个正整数都可以用2的幂次方表示。

#include <iostream>
#include <cmath>
using namespace std;
void f(int n)
{
    int i=0;
    if(n==1)
        {
            cout<<"2(0)";
            return ;
        }
    if(n==2)
        {
            cout<<"2";
            return ;
        }
    while(pow(2,i)<=n)        //从能找出2的最大的幂次方表示;
           i++;
    cout<<"2";
    if(i>2)                  //将较大的幂在进行进一步的分解为2的幂次方表示;
        {
            cout<<"(";
            f(i-1);
            cout<<")";
        }
    if(n-pow(2,i-1)!=0)
        {
            cout<<"+";
            f(n-pow(2,i-1));
        }

}
int main()
{
    int n;
    cin>>n;
    f(n);
}

总结:此题是开始找出最接近或是等于n的2的幂次方,然后剩下的数在寻找小一点的2的幂次方,以此递归下去。

总的的来说就是难以形成 递归的思想,和寻找递归的规则。期待之后能将递归思想贯穿于脑海。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值