引入:
函数是我们解决问题的一种重要手段,其中递归的使用尤为重要,在DFS,SPFA,线段树等算法中起到重要作用。而递归的时间复杂度相当高,那么有什么办法能优化递归呢?
其中我们着重来讲找规律这种方法,先看下面这道题:
对于一个递归函数w(a,b,c)。
如果a<=0 or b<=0 or c<=0就返回值1。
如果a>20 or b>20 or c>20就返回W(20,20,20)。
如果a<b并且b<c就返回w(a,b,c−1)+w(a,b−1,c−1)−w(a,b−1,c),
其它别的情况就返回w(a−1,b,c)+w(a−1,b−1,c) + w(a−1,b,c−1)−w(a−1,b-1,c -1)
这是个简单的递归函数,但实现起来可能会有些问题。
这道题乍一看是一道类似于阿克曼函数的简单函数递归题,连递归的条件与转移都告诉你了,但倾斜的字体告诉你了实际上问题没有这么简单。
int w(int a,int b,int c)
{
if (a<=0||b<=0||c<=0) return 1;
if (a>20||b>20||c>20) return w(20,20,20);
if (a<b&&b<c) return w(a,b,c−1)+w(a,b−1,c−1)−w(a,b−1,c);
else return w(a−1,b,c)+w(a−1,b−1,c)+w(a−1,b,c−1)−w(a−1,b-1,c-1);
}
如果按照题目中的写法应该是这样的。
呃, 意料之中的TLE了。
我们试着将a,b,c的几种取值情况进行枚举,看能不能找到突破口。
1 a>=b,b<=c,c<=a
2 a>=b,b<=c,c>=a
3 a>=b,b>=c
4 a<=b,b>=c,c<=a
5 a<=b,b>=c,c>=a
这五种情况是原来递归没有的条件。
第一种情况:
例如a,4 b,2 c,3 结果:18;a,5 b,3 c,4 结果:29,初步推断没有规律。
第二种情况:
例如a,3 b,2 c,4 结果:8;a,4 b,3 c,5 结果:16,初步推断2的a次方。
第三种情况:
例如a,5 b,4 c,3 结果:29;a,6 b,4 c,2 结果:81,初步推断没有规律。
第四种情况:
例如a,3 b,4 c,2 结果:8;a,5 b,6 c,3 结果:32,初步推断2的a次方。
第五种情况
例如a,4 b,5 c,3 结果:16;a,5 b,7 c,3 结果:32,初步推断2的a次方。
第六种情况
例如a,3 b,5 c,4 结果:8;a,45 b,7 c,6 结果:16,初步推断2的a次方。
这六种情况有四种是2的a次方这种类型,因此我们可以优化成:
ll w(ll a,ll b,ll c)
{
if (a<=0||b<=0||c<=0) return 1;
if (a>20||b>20||c>20) return poww(2,20);
if ((a==b&&b==c)||a<=b||(a>=b&&b<=c&&a<=c)) return poww(2,a);
else return w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}
这样就可以AC了。