首页 > 其他 > 详细

递归练习

时间:2019-08-07 22:06:29      阅读:173      评论:0      收藏:0      [点我收藏+]

一、集合的划分(信息学奥赛一本通-T1315):

关于集合自己并不是理解的很透彻:
关于a[i]的处理有两种:

1.a[i]是k个子集中的一个,于是便把a[1],a[2]......a[i - 1]划分为了k - 1个子集,这种情况共有s(n - 1, k - 1)个

2.a[i]不是k个子集中的一个,那么它肯定与其他元素构成一个子集,这种情况共有k * s(n - 1, k)个

根据乘法、加法原理,得到递归式:s(n, k) = s(n - 1, k - 1) + k * s(n - 1, k),然后注意一些边界条件,注意s很大,要开long long

技术分享图片
 1 #include<cstdio>
 2 #include<iostream>
 3 
 4 inline long long s(int n, int k){
 5     if(k == 1 || k == n) return 1;//边界 
 6     if(k == 0 || n < k) return 0;//边界 
 7     return s(n - 1, k - 1) + k * s(n - 1, k);//递归式 
 8 }
 9 
10 int main(){
11     int n, k;
12     scanf("%d%d", &n, &k);
13     printf("%lld", s(n, k));
14     return 0;
15 }
1315

 

 

二、数的计数(信息学奥赛一本通-T1316):

这道题暴力的递归会超时,所以用记忆化递归(类似记忆化搜索)来做...

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 
 4 using namespace std;
 5 
 6 int h[1005];
 7 
 8 inline void dfs(int x){
 9     if(h[x] != -1) return;//如果不等于-1,说明已经处理过了
10     h[x] = 1;//它本身一种情况
11     for(int i = 1; i <= x / 2; i++){
12         dfs(i);//按题目要求
13         h[x] += h[i];//i的情况肯定是x中的情况,因为i比x小
14     }
15 }
16 
17 int main(){
18     int n;
19     memset(h, -1, sizeof(h));//初始化
20     scanf("%d", &n);
21     dfs(n);
22     printf("%d", h[n]);
23     return 0;
24 }
1316

 

三、逆波兰表达式(信息学奥赛一本通-T1198):

这道题虽然说没有优先级,但是感觉隐隐约约还是有的:离数字越近的运算优先级越高...然后这个题中有一个函数:atof,用来把一个string类型的数变换成float类型...

技术分享图片
#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

char s[1000005];

inline double dfs(){
    scanf("%s", s);
    if(s[0] == +) return dfs() + dfs();
    else if(s[0] == -) return dfs() - dfs();
    else if(s[0] == *) return dfs() * dfs();
    else if(s[0] == /) return dfs() / dfs();
    else return atof(s);//函数 
}

int main(){
    printf("%f", dfs());
    return 0;
}
1198

 

四、全排列(信息学奥赛一本通-T1199):

这道题用到了回溯的一个思想:

我们如果长度达到了len,那么就输出。如果还没有,那么就一位一位枚举,如果它并没有在当前的序列中出现过,那么就把它加进来,然后找下一个。注意回溯...

技术分享图片
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 char s[10], now[10];
 8 int vis[10], len;
 9 
10 inline void dfs(int l){
11     if(l == len){
12         for(int i = 0; i < l; i++)
13             printf("%c", now[i]);
14         printf("\n");
15     }
16     else{
17         for(int i = 0; i < len; i++){
18             if(!vis[i]){
19                 now[l] = s[i];
20                 vis[i] = 1;
21                 dfs(l + 1);
22                 vis[i] = 0;//回溯 
23             }
24         }
25     }
26 }
27 
28 int main(){
29     scanf("%s", s);
30     len = strlen(s);
31     dfs(0);
32     return 0;
33 }
1199

 

五、分解因数(信息学奥赛一本通-T1200):

我们用a数组存储现在已经得到的这个元素的因数,然后看看除它以外还有多少因数,最后如果等于,则tot++,但是不明白为什么a[0]初始化为2...

技术分享图片
 1 #include<cstdio>
 2 #include<iostream>
 3 
 4 using namespace std;
 5 
 6 int m, a[40004], tot;
 7 
 8 inline void dfs(int x, int cur){
 9     int ans = 1;
10     for(int i = 1; i <= cur - 1; i++)
11         ans *= a[i];
12     if(ans == m) {tot++; return;}//正好 
13     if(ans > m) return;
14     for(int i = a[cur - 1]; i <= x; i++){
15         if(x % i == 0){ 
16             x /= i;
17             a[cur] = i;
18             dfs(x, cur + 1);
19             x *= i;//回溯 
20         }
21     }
22 }
23 
24 int main(){
25     int n;
26     scanf("%d", &n);
27     for(int i = 1; i <= n; i++){
28         scanf("%d", &m);
29         tot = 0;
30         a[0] = 2;
31         dfs(m, 1);
32         printf("%d\n", tot);
33     }
34     return 0;
35 }
1200

 

六、斐波那契数列(信息学奥赛一本通-T1201):

这道题可以直接用递推做,实在太水...

技术分享图片
 1 #include<cstdio>
 2 #include<iostream>
 3 
 4 using namespace std;
 5 
 6 int f[25], a;
 7 
 8 inline void work(){
 9     f[1] = 1;
10     f[2] = 1;
11     for(int i = 3; i <= 20; i++){
12         f[i] = f[i - 1] + f[i - 2];
13     }
14     return;
15 }
16 
17 int main(){
18     int n;
19     scanf("%d", &n);
20     work();
21     for(int i = 1; i <= n; i++){
22         scanf("%d", &a);
23         printf("%d\n", f[a]);
24     }
25     return 0;
26 }
1201

 

七、Pell数列(信息学奥赛一本通-T1202):

这道题跟T6太像了,注意不断的模就可以了...

技术分享图片
 1 #include<cstdio>
 2 #include<iostream>
 3 
 4 using namespace std;
 5 
 6 int a[1000005];
 7 
 8 inline void work(){
 9     for(int i = 3; i <= 1000005; i++)
10         a[i] = 2 * a[i - 1] % 32767 + a[i - 2] % 32767;
11     return;
12 }
13 
14 int main(){
15     int n;
16     scanf("%d", &n);
17     a[1] = 1;
18     a[2] = 2;
19     work();
20     for(int i = 1; i <= n; i++){
21         int x;
22         scanf("%d", &x);
23         printf("%d\n", a[x] % 32767);
24     }
25     return 0;
26 }
1202

 

 八、扩号匹配问题(信息学奥赛一本通-T1203):

这道题并没有看出有什么递归,只是用了两个栈进行模拟...竟然水过了!!

技术分享图片
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<stack>
 5 
 6 using namespace std;
 7 
 8 stack<int> st1;
 9 stack<int> st2;
10 
11 char s[105];
12 int vis[105], l;
13 
14 int main(){
15     while(scanf("%s", s) == 1){
16         memset(vis, 0, sizeof(vis));
17         l = strlen(s);
18         for(int i = 0; i < l; i++){
19             if(s[i] != ( && s[i] != [ && s[i] != ] && s[i] != )) continue;
20             if(s[i] == ( || s[i] == [){
21                 if(s[i] == () st1.push(i);
22                 else st2.push(i);
23             }
24             else if(s[i] == ) || s[i] == ]){
25                 if(s[i] == ) && !st1.empty()) {st1.pop(); continue;}
26                 if(st1.empty()) vis[i] = 2;
27                 if(s[i] == ] && !st2.empty()) {st2.pop(); continue;}
28                 if(st2.empty()) vis[i] = 2;
29             }
30             else{
31                 if(s[i] == ( || s[i] == [) vis[i] = 1;
32                 else vis[i] = 2;
33             }
34         }
35         while(!st1.empty()){
36             vis[st1.top()] = 1;
37             st1.pop();
38         }
39         while(!st2.empty()){
40             vis[st2.top()] = 1;
41             st2.pop();
42         }
43         printf("%s\n", s);
44         for(int i = 0; i < l; i++){
45             if(vis[i] == 1) printf("$");
46             else if(vis[i] == 2) printf("?");
47             else printf(" ");
48         }
49         printf("\n");
50     }
51     return 0;
52 }
53     
1203

 

九、爬楼梯(信息学奥赛一本通-T1204):

这道题只要手模一下即可得出规律:

f[1] = 1,f[2] = 2,f[x] = f[x - 1] + f[x - 2] (x > 2)

然后可以先全部预处理一下,也可以每一个都进行递归..

技术分享图片
 1 #include<cstdio>
 2 #include<iostream>
 3 
 4 using namespace std;
 5 
 6 
 7 inline int dfs(int x){
 8     if(x == 1) return 1;
 9     else if(x == 2) return 2;
10     else return dfs(x - 1) + dfs(x - 2);
11 }
12 
13 int main(){
14     int n;
15     while(scanf("%d", &n) == 1){
16         printf("%d\n", dfs(n));
17     }
18     return 0;
19 }
1204

 

十、

递归练习

原文:https://www.cnblogs.com/New-ljx/p/11299369.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!