0%

递归函数的设计技巧

理论基础

数学归纳法

  1. 验证P(1)成立
  2. 证明如果P(k)是正确的,那么P(k+1)也成立
  3. 联合1,2;证明由P(1)->p(n)成立

递归函数设计的三个重要部分

  1. 给递归函数应该明确的语义
  2. 实现边界条件时的程序逻辑
  3. 假设递归函数调用返回结果是正确的,实现本层函数逻辑

阶乘函数设计exp

1
2
3
4
5
6
7
8
#include<bits/stdc++.h>

int f(int n){
if(n==1){
return 1;
}
return n*f(n-1);
}

例题

HZOJ 184路飞吃桃

路飞买了一堆桃子不知道个数,第一天吃了一半的桃子,还不过瘾,又多吃了一个。以后他每天吃剩下的桃子的一半还多一个,到n天只剩下一个桃子了。路飞想知道一开始买了多少桃子。
太简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<bits/stdc++.h>

int f(int n){
if(n==1){
return 1;
}
return 2*(f(n-1)+1);
}

int main(){
int n;
scanf("%d", &n);
printf("%d\n", f(n));
}

HZOJ 186弹簧板

有一个小球掉落在一串连续的弹簧板上,小球落到某一个弹簧板后,会被弹到某一个地点,直到小球被弹到弹簧板以外的地方。

假设有 n 个连续的弹簧板,每个弹簧板占一个单位距离,a[i] 代表代表第 i 个弹簧板会把小球向前弹 a[i] 个距离。比如位置 1 的弹簧能让小球前进 2 个距离到达位置 3 。如果小球落到某个弹簧板后,经过一系列弹跳会被弹出弹簧板,那么小球就能从这个弹簧板弹出来。

现在小球掉到了1 号弹簧板上面,那么这个小球会被弹起多少次,才会弹出弹簧板。 1号弹簧板也算一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<bits/stdc++.h>

int f(int n,int a[],int i){
if(i>=n){
return 0;
}
return f(n,a,i+a[i])+1;
}



int main(){
int n;
scanf("%d", &n);
int a[n];
for(int i=0;i<n;i++){
scanf("%d", &a[i]);
}
printf("%d\n", f(n,a,0));
return 0;
}

HZOJ 235递归实现指数型枚举

​ 从 1−n 这 n 个整数中随机选取任意多个,每种方案里的数从小到大排列,按字典序输出所有可能的选择方案。

思想就是全排列然后分别取段枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<bits/stdc++.h>

int a[10];

void print(int n){
for(int i=0;i<n;i++){
if(i){
printf(" ");
}
printf("%d", a[i]);
}
printf("\n");
}

void fk(int i,int j,int n){
if(j>n){
return ;
}
for(int k=j;k<=n;k++){
a[i]=k;
print(i+1);
fk(i+1,k+1,n);
}
return ;
}

int main(){
int n;
scanf("%d",&n);
fk(0,1,n);
return 0;
}

差不多了,结束今天的算法之旅,明天复现一下L3HCTF(早知道就不去虾大玩了)