基本算法--递推

汉诺塔问题

将n个盘子从a移动到c所需要的最少移动次数?
首先设f[n]为移动n个盘子所需次数,将该问题分为三步:
(1)先将前n-1个盘子从a移动到b
(2)将最大的盘子移动到c
(3)最后将n-1个盘子从b移动到c
递推式为:f[n]=2*f[n-1]+1

放球问题

N球放入M盒,不允许出现空盒,共有多少种方案?
f[i][j]为将i个球放入j个盒子的方案数
  有i个球,首先在j个盒子中放入一个球,方案数为j*f[i-1][j]
  然后将i-1个球放入j-1个盒子中,方案数为f[i-1][j-1]
递推式为:f[i][j]=j*f[i-1][j]+f[i-1][j-1]

#include 
#include
using namespace std;
#define ll long long
ll res[25][25];
int main()
{
    memset(res,0,sizeof(res));
    int m,n,i,j;
    cin>>m>>n;
    for(i=1;i<=m;++i)
    {
        res[i][i]=1;
        res[i][1]=1;
    }
    for(i=2;i<=m;++i)
        for(j=2;j<=n;++j)
            res[i][j]=j*res[i-1][j]+res[i-1][j-1];
    cout<return 0;
}

使用一维数组节省内存空间

#include 
#include
using namespace std;
#define ll long long
ll f[21];
int main()
{
    memset(f,0,sizeof(f));
    int m,n,i,count=0;
    cin>>m>>n;
    for(i=1;i<=m;i++)
    {
        f[1]=f[i]=1;
        for(count=i-1;count>1;count--)
            f[count]=count*f[count]+f[count-1];
    }
    cout<return 0;
}

错排问题(装错信箱问题)

用A、B、C……表示写着n位友人名字的信封,a、b、c……表示n份相应的写好的信纸。把错装的总数为记作D(n)。假设把a错装进B里了,包含着这个错误的一切错装法分两类:
  (1)b装入A里,这时每种错装的其余部分都与A、B、a、b无关,应有D(n-2)种错装法。    
 (2)b装入A、B之外的一个信封,这时的装信工作实际是把(除a之外>  的)n-1份信纸b、c……装入(除B以外的)n-1个信封A、C……,显然这时装错的方法有D(n-1)种。
总之在a装入B的错误之下,共有错装法D(n-2)+D(n-1)种。a装入C,装入D……的n-2种错误之下,同样都有D(n-1)+D(n-2)种错装法
因此D(n)=(n-1)[D(n-1)+D(n-2)]

递推之卡特兰数

四类卡特兰数的应用:
1.括号化问题。  矩阵链乘: P=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?(h(n)种)
2.出栈次序问题。  一个栈(无穷大)的进栈序列为1,2,3,..n,有多少个不同的出栈序列?
3.将多边行划分为三角形问题。  将一个凸多边形区域分成三角形区域的方法数?
类似:在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数?
给顶节点组成二叉树的问题。
给定N个节点,能构成多少种形状不同的二叉树?  (一定是二叉树!)先去一个点作为顶点,然后左边依次可以取0至N-1个相对应的,右边是N-1到0个,两两配对相乘,就是h(0)*h(n-1) + h(2)*h(n-2) + … + h(n-1)h(0)=h(n)

利用卡特兰数递推求解:

令h(0)=1,h(1)=1,catalan数满足递推式:
h(n)= h(0)*h(n-1)+h(1)*h(n-2) + … + h(n-1)*h(0) (n>=2)
另类递推式: h(n)=((4*n-2)*h(n-1)/(n+1));
递推关系的解为:
h(n)=C(2n,n)/(n+1) (n=0,1,2,…)
递推关系的另类解为:
h(n)=c(2n,n)-c(2n,n-1)(n=0,1,2,…)

#include 
#include
using namespace std;
#define ll long long
ll res[35];
ll caculate(int n)
{
    if(res[n])  return res[n];
    return  res[n]=(4*n-2)*caculate(n-1)/(n+1);
}

int main()
{
    memset(res,0,sizeof(res));
    res[0]=1;
    res[1]=1;
    int n;
    cin>>n;
    cout<return 0;
}

你可能感兴趣的:(Algorithm)