某个递归题引发的思考

题目大意

给定一排长度为N(0<N<=50)的方格,向里面填入a,b,c三个数。要求任何相邻的方格数字不能相同,且首尾两格也不能相同。问:N个格子有几种填数方法

方法一(玄学大法)

首先进行暴力循环求结果得:
1 : 3
2 : 6
3 : 6
4 : 18
5 : 30
6 : 66
7 : 126

考虑到每一个数字开头都一样这里除以三发现:

1 : 1
2 : 2
3 : 2
4 : 6
5 : 10
6 : 22
7 : 42

发现当n>3时有规律 f(n) = f(n-1) + f(n-2)*2

提交后发现AC了
发现AC了
AC了
???

这样对学习递归没有好处,我们再看看常规方法

方法二(普通な方法)

首先当只有一个格子的时候不需要顾忌规则,显然有三种方法
当有两个格子的时候显然有六种方法
当有三个格子的时候通过排列发现也有六种方法

我们来思考一下有四个格子会怎么样
我们先列举当N=3的一种状态: 012
如果要是加一个格子去填数字的话是不是只能填1呢?由于规则
但是让你去列举的话难道就只能列出这一种吗?0101,0102他不行吗?
但是为什么光从N=3里列不出来呢?
因为规则!!!
所以我们需要从N=2去考虑一下。
我们看看N=2时的一种状态:01
给他加两个格子让他填数字的话可以怎么填呢?
上过高中数学的应该都懂吧?
第三个位置可以填 0,2,当填0的时候第四个位置可以填1或2,当填2的时候只能再填一个1
一共三种填法。但是有一种却是与N=3时的填法重复了我们需要去掉一个
即得出结果 f(4) = f(3) + (3-1)f(2) 有人可能会疑惑:为什么要去除从状态N=2种得出来得一种而不是从状态N=3的呢?

假设我们去掉了从状态N=3来的那么结果变成了f(4) = 3f(2),归纳总结得
f(n) = 3*f(n-2) 你会发现只满足了上述这一种情况,故不正确。

所以你会发现结果还是f(n) = f(n-1) + f(n-2)*2

不过这是一次运用递归思想而得出得结论,和那种瞎猜不一样

上代码:

#include <cstdio>
#include <cstring>
long long int ans[52];
int n;
/*
1 : 3       
2 : 6       
3 : 6
4 : 18
5 : 30
6 : 66
7 : 126
*/
int main()
{
    int i;
    ans[1] = 3;
    ans[2] = 6;
    ans[3] = 6;
    ans[4] = 18;//18
    for(i=5;i<=50;i++)
    {
        ans[i] = ans[i-1] + 2 * ans[i-2];
    }
    while(scanf("%d",&n) != EOF)
        printf("%lld\n",ans[n]*3);
    //for(i=1;i<=50;i++)printf("%d : %lld\n",i,ans[i]);
    return 0;
}

顺便说一下:任何递归能得出的结果用迭代的方式同样能得出来。目前你可以把迭代当作for循环

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值