第二部分 基础算法 --> 第四章 递归算法
递归算法
1315【例4.5】集合的划分
【题目描述】
设S是一个具有n个元素的集合,S=?a1,a2,……,an?,现将S划分成k个满足下列条件的子集合S1,S2,……,Sk ,且满足:
1.Si≠?
2.Si∩Sj=? (1≤i,j≤k,i≠j)
3.S1∪S2∪S3∪…∪Sk=S
则称S1,S2,……,Sk是集合S的一个划分。它相当于把S集合中的n个元素a1,a2,……,an 放入k个(0<k≤n<30)无标号的盒子中,使得没有一个盒子为空。请你确定n个元素a1,a2,……,an 放入k个无标号盒子中去的划分数S(n,k)。
【输入】给出n和k。
【输出】n个元素a1,a2,……,an 放入k个无标号盒子中去的划分数S(n,k)。
【输入样例】10 6
【输出样例】22827
【题解】
点击查看代码
1316【例4.6】数的计数(Noip2001)
【题目描述】我们要求找出具有下列性质数的个数(包括输入的自然数n)。先输入一个自然数n(n≤1000),然后对此自然数按照如下方法进行处理:
不作任何处理;
在它的左边加上一个自然数,但该自然数不能超过原数的一半;
加上数后,继续按此规则进行处理,直到不能再加自然数为止。
【输入】自然数n(n≤1000)。
【输出】满足条件的数。
【输入样例】6
【输出样例】6
【样例解释】满足条件的数为如下所示:
6
16
26
126
36
136
【题解】
点击查看代码
1198 逆波兰表达式
【题目描述】逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3。逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* + 2 3 4。本题求解逆波兰表达式的值,其中运算符包括+ - * /四个。
【输入】输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数。
【输出】输出为一行,表达式的值。可直接用printf("%f\n", v)输出表达式的值v。
【输入样例】* + 11.0 12.0 + 24.0 35.0
【输出样例】1357.000000
【题解】
点击查看代码
1199 全排列
【题目描述】给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。
我们假设对于小写字母有‘a’ <‘b’ < ... <‘y’<‘z’,而且给定的字符串中的字母已经按照从小到大的顺序排列。
【输入】只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在1到6之间。
【输出】输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字母序如下定义:
已知S=s1s2...sk,T=t1t2...tk,则S<T等价于,存在p(1<=p<=k),使得s1=t1,s2=t2,...,sp?1=tp?1,sp<tp成立。
【输入样例】
abc
【输出样例】
abc
acb
bac
bca
cab
cba
【题解】
#include<stdio.h>
#include<string.h>
int n;
int vis[10], cnt=-1;
char a[10], s[10];
void sort(char arr[], int l, int r) {
for(int i=r; i>=l; i--) {
for(int j=l; j<i; j++) {
if(arr[j]>arr[j+1]) {
char temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
void dfs(int m) {
if(m>n) {
printf("%s\n",s); return;
}
for(int i=0; i<n; i++) {
if(!vis[i]) {
vis[i]=1;
s[++cnt]=a[i];
dfs(m+1);
--cnt;
vis[i]=0;
}
}
}
int main() {
scanf("%s", a);
n=strlen(a);
sort(a, 0, n-1);
dfs(1);
return 0;
}
1200 分解因数
【题目描述】给出一个正整数a,要求分解成若干个正整数的乘积,即a=a1×a2×a3×...×an,并且1<a1≤a2≤a3≤...≤an,问这样的分解的种数有多少。注意到a=a也是一种分解。
【输入】第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a(1<a<32768)。
【输出】n行,每行输出对应一个输入。输出应是一个正整数,指明满足要求的分解的种数。
【输入样例】
2
2
20
【输出样例】
1
4

浙公网安备 33010602011771号