问题 A: 递归求解 时间限制: 5 Sec 内存限制: 128 MB 提交: 6 解决: 2 201501010119 提交状态讨论版 题目描述 使用递归编写一个程序,求以下数列的前n项: s=1−12 +13 −14 +15 −16 +....+1n s=1−12+13−14+15−16+....+1n 输入 多组数据输入,每组输入一个正整数n 输出 输出前n项的结果(精确到小数点后六位) 样例输入 Copy 1 样例输出 Copy 1.000000
#include <bits/stdc++.h> using namespace std; double f(int n) { if(n==1) return 1; else if(n%2==0) { return f(n-1.0)-1.0/n; } else if(n%2!=0) { return f(n-1)+1.0/n; } } int main() { int n; while(scanf("%d",&n)!=EOF) { printf("%.6f\n",f(n)); } return 0; }
问题 D: 数的划分 时间限制: 1 Sec 内存限制: 128 MB 提交: 0 解决: 0 201501010119 提交状态讨论版 题目描述 使用递归编写一个程序,求一个正整数n的所有划分个数。 例如,输入3,输出3;输入4,输出5。 输入 多组输入,每一组是一个正整数n。 输出 输出划分数。 样例输入 Copy 3 4 样例输出 Copy 3 5
感觉这个题和分苹果有点类似(前面写过);
f(3)=3,f(4)=5,f(6)=11;
题目意思:将一个正整数划分为几个正整数;
3的分法:3;2+1;1+1+1
4的分法:4;2+2;1+3;1+2+1;1+1+1+1
6的分法:6;1+5;4+2;4+1+1;3+3;3+2+1;3+1+1+1;2+2+2;2+2+1+1;2+1+1+1+1;1+1+1+1+1+1
设n,m;将n分解成不大于m的数设为:f(n,m),意思是:举个栗子,f(6,3),将6分成不大于3的数的分法,这样分:3,3; 3,2,1; 3,1,1,1;
这样看来,f(6,3)的分法可以由n-m的数(称为剩下的数)有几种分法;
所以f(6,3)由两种分法组成,第一种是f(3,3)组成(被减掉的最大数),第二种是被减掉剩下的数的划分方法,也就是f(6,2);
这个就是我们的一般规律;
现在来讨论特殊情况:
f(n,1)=1,n>=1; 将n分解成n个1,只有一种分法;
f(n,m),n<m, 其实就等于f(n,n); 所以f(1,m)=1;
f(n,n)=f(n,n-1)+1(自己等于自己的情况,举个栗子:6分成6); f(n,n-1)又可以递归到f(n,m)的一般情况;
#include <bits/stdc++.h> using namespace std; int q(int n,int m) { if((n<1)||(m<1)) { return 0; } if((n==1)||(m==1)) { return 1; } if(n<m) return q(n,n); if(n==m) return q(n,m-1)+1; else return q(n,m-1)+q(n-m,m); } int main() { int n; while(cin>>n) { q(n,n); //输入情况是这样子 cout<<q(n,n)<<endl; } return 0; }
感觉这题的难点就是要想到如何分解整数,按照哪几个条件来分;
大概递归树就是这样子的吧~
问题 A: 递归求解 时间限制: 5 Sec 内存限制: 128 MB 提交: 6 解决: 2 201501010119 提交状态讨论版 题目描述 使用递归编写一个程序,求以下数列的前n项: s=1−12 +13 −14 +15 −16 +....+n s=1−12+13−14+15−16+....+n 输入 多组数据输入,每组输入一个正整数n 输出 输出前n项的结果(精确到小数点后六位) 样例输入 Copy 1 样例输出 Copy 1.000000
#include <bits/stdc++.h> using namespace std; double f(int n) { if(n==1.0) return 1; else if(n%2==0) { return f(n-1.0)-1.0/n; } else if(n%2!=0) { return f(n-1)+1.0/n; } } int main() { int n; while(scanf("%d",&n)!=EOF) { printf("%.6f\n",f(n)); } return 0; }
问题 E: 汉诺塔 时间限制: 1 Sec 内存限制: 128 MB 提交: 0 解决: 0 201501010119 提交状态讨论版 题目描述 使用递归编写一个程序实现汉诺塔问题,要求在输入圆盘数量之后,输出圆盘的移动步骤,输出格式示例如下: 第1步:1号盘从A柱移至B柱 第2步:2号盘从A柱移至C柱 输入 多组测试用例,每组输入一个正整数n,n代表圆盘数量。 输出 每组输出之间有一行空行。 样例输入 Copy 3 样例输出 Copy 第1步:1号盘从A柱移至C柱 第2步:2号盘从A柱移至B柱 第3步:1号盘从C柱移至B柱 第4步:3号盘从A柱移至C柱 第5步:1号盘从B柱移至A柱 第6步:2号盘从B柱移至C柱 第7步:1号盘从A柱移至C柱
#include <bits/stdc++.h> using namespace std; int s=0; void move(int n,char a,char b) { printf("第%d步:%d号盘从%c柱移至%c柱\n",++s,n,a,b); } void hano(int n,char a,char b,char c) //从a移到c借助b { if(n==1) { move(1,a,c); } else { hano(n-1,a,c,b); move(n,a,c); hano(n-1,b,a,c); } } int main() { int n; while(scanf("%d",&n)!=EOF) { s=0; hano(n,‘A‘,‘B‘,‘C‘); //注意ABC要打单引号 cout<<endl; } return 0; }
本题个人感觉难点是存总步数(第几步第几步...)
所以用一个全局变量来存,并在每次输入的时候重新归零;
问题 B: 字母全排列 时间限制: 1 Sec 内存限制: 128 MB 提交: 2 解决: 1 201501010119 提交状态讨论版 题目描述 编写一个程序,使用递归算法输出一个一维字符数组中所有字符的全排列,假设字符都不一样。例如{‘a‘,‘b‘,‘c‘}的全排列为(a,b,c), (a,c,b), (b,a,c), (b,c,a), (c,a,b), (c,b,a) 输入 多组测试用例,每组输入一个正整数n(0<n<=26)。 输出 输出从a开始,连续n个字母的全排列,且每组输出之间用空格隔开。 样例输入 Copy 1 2 样例输出 Copy a ab ba
#include<bits/stdc++.h> using namespace std; void swap(char a[],int i,int j) { int t=a[i]; a[i]=a[j]; a[j]=t; } void f(char a[],int k,int n) { if(k>=n) //只剩下一个元素 { for(int i=0;i<n;i++) printf("%c",a[i]); cout<<endl; } else { for(int i=k;i<n;i++) //循环用来判断每次排列谁做第一个,递归用来递归到下一个元素的判断 { swap(a,k,i); //还原 f(a,k+1,n); swap(a,k,i); //还原 } } } int main() { int n; while(cin>>n) { char a[27]; int i; int s=97; for(i=0;i<n;i++) { a[i]=s; s++; } f(a,0,n); cout<<endl; } return 0; }
这个题和书上的数字全排列问题类似(划掉);
全排列问题的核心思想是:各个排列数轮流做第一个;
分两步:n=1,只有一个元素;n>1,一直递归到只剩下一个元素;
注意点:轮流做完了第一个后要还原!
问题 F: 幸运人士 时间限制: 1 Sec 内存限制: 128 MB 提交: 1 解决: 1 201501010119 提交状态讨论版 题目描述 一次大型派对的最后节目是选出一位幸运人士,该人士将获得派对组织者准备的一个钻石戒指。 而选择幸运人士的办法是让所有人员一字排列,然后从左至右点数,凡是奇数号的全部剔除。 对于剩下的人员,又从左至右点数,逢奇数号就剔除。 如此不断递归下去,直到只剩下一个人为止,此人即为幸运之人。 请设计一个递归算法计算幸运之人所在的位置。 输入 多组数据,每组输入一个正整数n。 输出 输出最后剩下的那个人的位置。 样例输入 Copy 1 2 3 样例输出 Copy 1 2 2
#include <bits/stdc++.h> using namespace std; int f(int a,int b) { if(a>1) { if(a%2==0) { b++; return f(a/2,b); } if(a%2!=0) { b++; return f(a/2,b); } } if(a==1) return b; } int main() { int n; while(cin>>n) { int s,i,c; c=1; s=f(n,0); for(i=0;i<s;i++) c=c*2; cout<<c<<endl; } return 0; }
算。。。水题?找规律?之前一直以为用数组,后来室友发现了规律
问题 C: 九数组分数 时间限制: 1 Sec 内存限制: 128 MB 提交: 0 解决: 0 201501010119 提交状态讨论版 题目描述 1, 2, 3...9 这九个数字组成一个分数,其值恰好为1/3,要求每个数字出现且只能出现一次,如何组合?编写程序输出所有的组合。 输入 无 输出 输出所有的结果,如果有多个,每条结果占一行。 结果的格式 : xxxx/xxxxx ,按照分子从小到大的顺序输出。
#include<bits/stdc++.h> using namespace std; int arr[2]; int k=0; void f(int aa[],int m,int n) { if(m==n) { int a,b; a=aa[3]*1000+aa[2]*100+aa[1]*10+aa[0]; b=aa[8]*10000+aa[7]*1000+aa[6]*100+aa[5]*10+aa[4]; if(a*3==b) arr[k++]=a; } else { int i; for(i=m;i<=n;i++) { swap(aa[m],aa[i]); f(aa,m+1,n); swap(aa[m],aa[i]); } } } int main() { int aa[]={1,2,3,4,5,6,7,8,9}; f(aa,0,8); sort(arr,arr+2); for(int j=0;j<2;j++) printf("%d/%d\n",arr[j],arr[j]*3); return 0; }
和全排列类似;
判断比值恰好为三分之一,将除法转换为乘法来算
问题 H: 汉诺塔-3 时间限制: 1 Sec 内存限制: 32 MB 提交: 1 解决: 1 201501010119 提交状态讨论版 题目描述 用1,2,...,n表示n个盘子,称为1号盘,2号盘,...。号数大盘子就大。经典的汉诺塔问题经常作为一个递归的经典例题存在。可能有人并不知道汉诺塔问题的典故。汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘。我们知道最少需要移动2^64-1次.在移动过程中发现,有的圆盘移动次数多,有的少 。 告之盘子总数和盘号,计算该盘子的移动次数. 输入 包含多组数据,首先输入T,表示有T组数据.每个数据一行,是盘子的数目N(1<=N<=60)和盘号k(1<=k<=N)。 输出 对于每组数据,输出一个数,到达目标时k号盘需要的最少移动数。 样例输入 Copy 2 60 1 3 1 样例输出 Copy 576460752303423488 4
#include<bits/stdc++.h> using namespace std; int main() { int t,n,k; cin>>t; while(t--) { cin>>n>>k; int long long s,a; int i; s=1; a=n-k; for(i=0;i<a;i++) { s=s*2; } cout<<s<<endl; } return 0; }
这个也算找规律?
贴一个别人总结的汉诺塔问题
原文:https://www.cnblogs.com/liufei-/p/10555526.html