递归专练

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/84946056

p1112 取数问题

题目

描述 Description
我们来玩一个游戏:自然数1到N,按顺序列成一排,你可以从中取走任意个数,但是相邻的两个不可以同时被取走。如果你能算出一共有多少种取法,那么你会被天神Liushiji奖励。
输入格式 Input Format
一个数n(1< n < 50)。
输出格式 Output Format
仅包含一个数——你的答案。
样例输入 Sample Input

5
样例输出 Sample Output

13
时间限制 Time Limitation
1s

代码

#include<iostream>
using namespace std;
long long n,MAX;
long long F[1110];
long long f(int n)
{
	if(F[n]!=0) return F[n];
	if(n==1) return F[n]=2;
	if(n==2) return F[n]=3;
	return F[n]=f(n-1)+f(n-2);
}
int main()
{
    cin>>n;
	f(n);
	cout <<f(n)<<endl;
	return 0;
}

p1113 2的幂次方

题目

描述 Description
任何一个正整数都可以用2的幂次方表示。例如:
    137=27+23+2^0    
同时约定方次用括号来表示,即ab 可表示为a(b)。
   由此可知,137可表示为:
     2(7)+2(3)+2(0)
进一步:7= 22+2+20 (21用2表示)
     3=2+2^0
所以最后137可表示为:
     2(2(2)+2+2(0))+2(2+2(0))+2(0)
   又如:
     1315=2^10 +2^8 +2^5 +2+2^0
所以1315最后可表示为:
   2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
  输入:正整数(n≤20000)
  输出:符合约定的n的0,2表示(在表示中不能有空格)
输入格式 Input Format
一个正整数
输出格式 Output Format
符合约定的n的0,2表示(在表示中不能有空格)
样例输入 Sample Input

73
样例输出 Sample Output

2(2(2)+2)+2(2+2(0))+2(0)
时间限制 Time Limitation
1s

代码

#include<bits/stdc++.h>
#include<cstdio>
using namespace std;
void power(int n)
{
	if(n==1)
	{
		printf("2(0)");
		return;
	}
	if(n==2)
	{
		printf("2");
		return;
	}
	int p=1,s=0;
	while(p<=n)
	{
		p*=2;
		s++;
	}
	s=s-1;
	if(n==p/2)
	{
		printf("2(");
		power(s);
		printf(")");
	}else
	{
		if(p/2==2)
		{
			printf("2");
			printf("+");
			power(n-p/2);
		}
	    else
	    {
		    printf("2(");
		    power(s);
		    printf(")+");
		    power(n-p/2);
		}
    }
}
int main()
{
	int n;
	scanf("%d",&n);
	power(n);
}

p1114 拍卖

题目

描述 Description
一般情况下,拍卖行的拍卖师在拍卖商品的时候都是从低价开始起拍,由买方报价,最后谁出的价格高,商品就归谁所有。但焦作有个拍卖行,拍卖师在拍卖商品时正好相反:总是从高价开始起拍,如果没有人举成交牌就降价,而且拍卖师在降价时还有规律:假如第i次报价为w元,那么第i+1次报价为w-a或者w-b元,如果降到p元时,你认为价格合适,赶快第一个举成交牌,你就花p元买下了商品。

任务:拍卖师把商品从w元降到p元的方法总数。
输入格式 Input Format
文件第一行有两个正整w 和p ,第二行有有两个正整a 和b.
1 ≤ w,p ≤ 10^6  , 2 ≤ a,b ≤ 10000, a不等于b.
输出格式 Output Format
文件只有一行,即所求得的方法总数。注意:测试数据中方法总数不超过MAXlongint.
样例输入 Sample Input

10 3
2 3

样例输出 Sample Output

3
时间限制 Time Limitation
1s

代码

#include<bits/stdc++.h>
using namespace std;
long long F[1000020];
int w,p,a,b,ans;
int d(int t)
{
	if(F[t]>=0) return F[t];
	if(t==p) return 1;
	if(t<p) return 0;
	F[t]=d(t-a)+d(t-b);
	return (F[t]);
}
int main()
{
	cin>>w>>p>>a>>b;
	ans=0;
	memset(F,-1,sizeof(F));
	F[p]=1;
	cout<<d(w);
	return 0;
}

p1115 集合划分问题

题目

描述 Description
n 个元素的集合{1,2,., n }可以划分为若干个非空子集。例如,当n=4 时,集合{1,2, 3,4}可以划分为15 个不同的非空子集如下:
{{1},{2},{3},{4}},
{{1,2},{3},{4}},
{{1,3},{2},{4}},
{{1,4},{2},{3}},
{{2,3},{1},{4}},
{{2,4},{1},{3}},
{{3,4},{1},{2}},
{{1,2},{3,4}},
{{1,3},{2,4}},
{{1,4},{2,3}},
{{1,2,3},{4}},
{{1,2,4},{3}},
{{1,3,4},{2}},
{{2,3,4},{1}},
{{1,2,3,4}}
其中,集合{{1,2,3,4}} 由1 个子集组成;集合{{1,2},{3,4}},{{1,3},{2, 4}},{{1,4},{2,3}},{{1,2,3},{4}},{{1,2,4},{3}},{{1,3,4},{2}},{{2, 3,4},{1}} 由2 个子集组成;集合{{1,2},{3},{4}},{{1,3},{2},{4}},{{1,4}, {2},{3}},{{2,3},{1},{4}},{{2,4},{1},{3}},{{3,4},{1},{2}} 由3 个子集组成;集合{{1},{2},{3},{4}} 由4 个子集组成。

编程任务:

给定正整数n 和m,计算出n 个元素的集合{1,2,., n }可以划分为多少个不同的由m 个非空子集组成的集合。
输入格式 Input Format
第1 行是元素个数n 和非空子集数m。
0<m<n<=60
输出格式 Output Format
将计算出的不同的非空子集数输出.
样例输入 Sample Input

4 3
样例输出 Sample Output

6
时间限制 Time Limitation
1s
注释 Hint
递归公式,

设n个元素的集合可以划分为F(n,m)个不同的由m个非空子集组成的集合。

F(n,m) = 1, when n=0, n=m, n=1, or m=1

F(n,m) = 0, when n<m

否则

F(n,m)=F(n-1,m-1)+m*F(n-1,m)

例如:

考虑3个元素的集合,可划分为

① 1个子集的集合:{{1,2,3}}

② 2个子集的集合:{{1,2},{3}},{{1,3},{2}},{{2,3},{1}}

③ 3个子集的集合:{{1},{2},{3}}

∴F(3,1)=1;F(3,2)=3;F(3,3)=1;

如果要求F(4,2)该怎么办呢?

A.往①里添一个元素{4},得到{{1,2,3},{4}}

B.往②里的任意一个子集添一个4,得到

{{1,2,4},{3}},{{1,2},{3,4}},

{{1,3,4},{2}},{{1,3},{2,4}},

{{2,3,4},{1}},{{2,3},{1,4}}

∴F(4,2)=F(3,1)+2F(3,2)=1+23=7
来源 Source
经典题目

代码

#include<bits/stdc++.h>
using namespace std;
int n,m;
long long dfs(int n,int m)
{

	if(n==0||n==m||n==1||m==1) return 1;
	if(n<m) return 0;	
	return dfs(n-1,m-1)+dfs(n-1,m)*m;
}
int main()
{
	cin>>n>>m;
    dfs(n,m);
	cout<<dfs(n,m);
	return 0;
}

p1116 超级书架

题目

描述 Description
  Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此
的大,但它还是几乎瞬间就被各种各样的书塞满了。现在,只有书架的顶上还留
有一点空间。
  所有N(1 <= N <= 20)头奶牛都有一个确定的身高H_i(1 <= H_i <= 1,000,000 - 好高的奶牛>_<)。设所有奶牛身高的和为S。书架的高度为B,并且保证1 <= B <= S。

为了够到比最高的那头奶牛还要高的书架顶,奶牛们不得不象演杂技一般,一头站在另一头的背上,叠成一座“奶牛塔”。当然,这个塔的高度,就是塔中所有奶牛的身高之和。为了往书架顶上放东西,所有奶牛的身高和必须不小于书架的高度。

塔叠得越高便越不稳定,于是奶牛们希望找到一种方案,使得叠出的塔在高
度不小于书架高度的情况下,高度尽可能小。你也可以猜到你的任务了:写一个
程序,计算奶牛们叠成的塔在满足要求的情况下,最少要比书架高多少。

输入格式 Input Format
* 第1行: 2个用空格隔开的整数:N 和 B

  • 第2…N+1行: 第i+1行是1个整数:H_i
    输出格式 Output Format
    • 第1行: 输出1个非负整数,即奶牛们叠成的塔最少比书架高的高度
      样例输入 Sample Input

5 16
3
1
3
5
6

样例输出 Sample Output

1
时间限制 Time Limitation
1s
注释 Hint
输出说明:
  我们选用奶牛1、3、4、5叠成塔,她们的总高度为3 + 3 + 5 + 6 = 17。任何方案都无法叠出高度为16的塔,于是答案为1。

代码

#include<bits/stdc++.h>
using namespace std;
int sum,n,b;
const int MAXN=100000+10;
int f[MAXN],h[MAXN];
int main()
{
	cin>>n>>b;
	for(int i=1;i<=n;i++) cin>>h[i];
	sort(h+1,h+n+1);
	for(int i=1;i<=n;i++) sum+=h[i];
	int k=sum-b;
	for(int i=1;i<=n;i++)
    {
        for(int j=k;j>=h[i];j--)
		f[j]=max(f[j],f[j-h[i]]+h[i]);
    }
	cout<<k-f[k];
	return 0;
}

p1117 倒牛奶(Milk3)

题目

描述 Description
农民约翰有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数,
最初,A和B桶都是空的,而C桶是装满牛奶的。有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。当然每一次灌注都是完全的。由于节约,牛奶不会有丢失。
写一个程序去帮助约翰找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。
输入格式 Input Format
单独的一行包括三个整数A,B和C。
输出格式 Output Format
只有一行,升序地列出当A桶是空的时候,C桶牛奶所剩量的所有可能性。
样例输入 Sample Input

SAMPLE INPUT 1
8 9 10

SAMPLE INPUT 2
2 5 10

样例输出 Sample Output

SAMPLE OUTPUT 1
1 2 8 9 10

SAMPLE OUTPUT 2
5 6 7 8 9 10

时间限制 Time Limitation
1s

代码

#include<bits/stdc++.h>
using namespace std;
int A,B,C,t=0;
const int MAX=25;
int num1[MAX][MAX][MAX];
int num[MAX],sum[120000]={0};
void f(int a,int b,int c)
{
	if(num1[a][b][c]==0) 
	{
	   if(a==0) sum[++t]=c;
		num1[a][b][c]=1;
	   if(c>=A-a) f(A,b,c-A+a); else f(a+c,b,0);
        if(c>=B-b) f(a,B,c-B+b); else f(a,b+c,0); 
        if(a>=C-c) f(a-C+c,b,C); else f(0,b,c+a);
        if(a>=B-b) f(a-B+b,B,c); else f(0,b+a,c);
        if(b>=C-c) f(a,b-C+c,C); else f(a,0,b+c);
        if(b>=A-a) f(A,b-A+a,c); else f(a+b,0,c);
	}
    	else return;
}
int main()
{
	cin>>A>>B>>C;
	memset(num1,0,sizeof(num1));
	f(0,0,C);
	sort(sum+1,sum+t+1);
	for(int i=1;i<=t;i++)
		cout<<sum[i]<<' ';
	cout<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/84946056