1227讲解(递归deng)

递归:

迭代为人,递归为神。

老和尚讲故事

从前有座山,山上有座庙,庙里有个老和尚,老和尚他说:“从前有座山,山上有座庙,庙里有个老和尚,老和尚他说:‘从前有座山,山上有座庙,庙里有个老和尚,老和尚他说:’ ”...

void的函数调用自身

电影院问座位(递和归的过程)

假设黑暗中一群懒人在电影院里,某人想知道自己坐在哪一排,于是问前一排的人「你坐在哪一排?」,前面的人 (代号 A) 回答后,他就知道自己在哪一排了——只要把 A 的答案加一就行。不料 A 比他还懒,也不想数,也问他前面的人 B「你坐在哪一排?」,这样 A 可以用和他一模一样的步骤知道自己所在的排。然后 B 也如法炮制。直到他们这一串人问到了最前面的一排,第一排的人告诉问问题的人「我在第一排」。最后大家就都知道自己在哪一排了。

返回值

用递归方法来解决问题必须符合两个条件:

可以把一个问题转化成一个新的问题,而新问题的解法和原问题的解法完全相同,只是处理对象的规模不同

必须要有一个明确的递归终止条件

 

例,求n!

int f(int n){
    if(n==1) return 1;
    if(n>1) return n*f(n-1);
}
int main(){
    int n;
    cin>>n;
    cout<


1242楼梯(记忆处理)

Description

楼梯有n(n<=40)阶台阶。
上楼可以一步上1阶,也可以一步上2阶。
编一程序计算上n阶台阶共有多少种不同的走法?

Input

输入n

Output

输出走法总数

Sample Input

3

Sample Output

3

long long f(int n){
	if(n==1)return 1;
	if(n==2)return 2;
	return f(n-1)+f(n-2);	
}
int main(){
	int n;
	cin>>n;
	cout<

中间有很多重复调用的过程,可以将已经调用过的记录下来直接使用,避免重复调用。

long long a[45]={0,1,2};
long long f(int n){
	if(a[n])return a[n];
	return a[n]=f(n-1)+f(n-2);	
}
int main(){
	int n;
	cin>>n;
	cout<


1244错排问题的推导

Description

某人写了n封信和n个信封,如果所有的信都装错了信封。求所有的信都装错信封共有多少种不同情况。

Input

输入n(n <=20)

Output

输出情况总数

Sample Input

2

Sample Output

1

 

如:1,2,3,4,5等n本书

当1和后面的n-1本书中的某本书交换位置时,剩下的n-2本书就是n-2的错排。因此排列方式为 (n-1)*f(n-2)(乘法原理)

如果交换的这本书不放在1的位置,那么就是n-1本书的错排。排列方式为 (n-1)*f(n-1)

总的排列方式为:(n-1)*f(n-2)+ (n-1)*f(n-1) (加法原理)

 

long long a[45];
long long f(int n){  
	if(n==1)return 0;
    if(n==2) return a[2]=1;
    if(a[n]) return a[n];
	return a[n]=(n-1)*(f(n-1)+f(n-2));	
}
int main(){
	int n;
	cin>>n;
	cout<

 

1241汉诺塔(要求写出调用过程)

Description

汉诺塔问题:设有三个塔座,依次命名为A,B,C。有n个直径不同的圆盘,由小到大依次编号为1,2,…,n。
开始时,它们全部按递减的次序插在塔座A上。现要求按下列规则把n个圆盘按次序插放在C塔座上。
(1)每次只能移动一个圆盘;
(2)圆盘可以从任一个塔座上移到另一个塔座上;
(3)任何时刻都不能把一个较大的圆盘压在较小的圆盘上。

Input

输入n(n<=20)

Output

输出移动过程

Sample Input

3

Sample Output

A->C

A->B

C->B

A->C

B->A

B->C

A->C

void hanoi(int n,char a,char b,char c){
	if(n==1){
		cout<"<1){
		hanoi(n-1,a,c,b);
		cout<"<>n;
	hanoi(n,'A','B','C'); 
	return 0;
}

 

 

介绍重庆市第十届大学生程序设计比赛情况

做练习:A.狂小P猜密码

狂小P想解锁快乐C的iPhone,但是他只知道解锁密码由四位0~9的阿拉伯数字组成。

现在给你一个长度为10的数组d[0...9],保证对于,有di = 0表示数字i没有在解锁密码中出现,di = 1表示数字i在解锁密码中出现至少一次。

狂小P现在想知道有多少种解锁密码满足上述条件。

Input

输入仅一行,包含10个整数,表示d[0...9]。

Output

输出仅一个整数,表示答案。

Examples

input

1 1 1 1 0 0 0 0 0 0
output

24

input

0 0 0 0 0 0 0 0 0 0

output

0

不难的题目,但比赛中有时不能正确理解题意导致出错。

int a,s;
int main(){
	for(int i=0;i<10;i++){
		cin>>a;
		if(a==1)s++;
	}
	if(s==0||s>4)cout<<0;
	if(s==1)cout<<1;
	if(s==2)cout<<14;
	if(s==3)cout<<36;
	if(s==4)cout<<24;
	return 0;
}


 

 

 

你可能感兴趣的:(OI)