1.一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子?
(1)题目分析:
经过7个村子后还剩下两只鸭子,每经过一个村庄卖当前鸭子的一半加一只,所以递归出口为经过第七个村子剩下的两只,递归体为经过下一个村子的鸭子数加1乘以2就是当前村子的鸭子数。
(2)算法构造:
total(number)=2; number=7
total(number)=(total(number+1)+1)*2 0<number<7
代码实现如下:
/*
Author:王连霞
date:2018-11-15
version:1.0
desciption:通过递归实现一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子?
*/
#include <iostream>
using namespace std;
int x;
int total(int number) //递归函数,number表示经过的村子数
{
if(number==7) //递归出口,当经过第七个村子后,剩下两只鸭子
{
return 2;
}
else {
return (total(number+1)+1)*2; //递归体,鸭子总数为经过后一天鸭子数+1乘以2
}
}
/*主函数*/
void main()
{ cout<<"他总共赶了"<<total(0)<<"只鸭子"<<endl;
for(int i=7;i>0;i--)
{
cout<<"他经过第"<<i<<"个村子卖出"<<(total(i-1)/2+1)<<"只鸭子"<<endl;
}
}
运行结果:
2.
2.角谷定理。输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以3加1。经过如此有限次运算后,总可以得到自然数值1。求经过多少次可得到自然数1。
如:输入22,
输出 22 11 34 17 52 26 13 40 20
10 5 16 8 4 2 1
STEP=16
(1) 题目分析:设fun(n)表示关于自然数n的一个函数,由题意已知,当n=1时,fun(1)=1。当n>1且n为偶数时,fun(n)=fun(n/2);当
n>1且n为奇数时,fun(n)=fun(3*n+1)。得到自然数1的运算次数为每次运算次数之和。
(2) 算法构造:
fun(n)=1 ,n=1
fun(n)=fun(n/2) ,n>1且n为偶数
fun(n)=fun(3*n+1) ,n>1且n为奇数
(3) 代码实现:
/*
Author:王连霞
date:2018-11-15
version:1.0
desciption:通过递归实现 角谷定理。输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以3加1。经过如此有限次运算后,总可以得到自然数值1。求经过多少次可得到自然数1。*/
#include <iostream>
using namespace std;
int function(int *step,int n) //递归函数,step表示步数,n表示输入的数
{
if(n==1) //递归出口,当n为1时结束递归调用
{
return 1;
}
if(n%2==0) //递归体,当n为偶数时将其除以2
{
cout<<n<<endl;
(*step)++;
return function(step,n/2);
}
else if(n%2!=0) //递归体,当n为奇数时将其乘以3加1
{
cout<<n<<endl;
(*step)++;
return function(step,n*3+1);
}
}
void main()
{
int n;
int step=1;
cout<<"请输入你的数字:"<<endl;
cin>>n;
function(&step,n); //调用递归函数
cout<<"总的步数为"<<step<<endl;
}
(4)运行结果:
3.
3.电话号码对应的字符组合:在电话或者手机上,一个数字如2对应着字母ABC,7对应着PQRS。那么数字串27所对应的字符的可能组合就有3*4=12种(如AP,BR等)。现在输入一个3到11位长的电话号码,请打印出这个电话号码所对应的字符的所有可能组合和组合数。
(1)题目分析
1,0——1""
2——3"ABC"
3——3"DEF"
4——3"GHI"
5——3"JKL"
6——3"MNO"
7——4"PQRS"
8——3"TUV"
9——4"WXYZ"
并且两个数字是相乘关系
(2)算法构造:
递归出口是,当输入的是一个数字时,返回这个数字所有可能性的组合,递归体是当输入一串数字,每个数字代表不同的字符串,返回最后一个数字跟前面已产生的字符串进行组合,首先建一个数组,用来存放每个数字代表的字符串组合,然后再建一个数组,用来存放每个字符串的长度
(3)代码实现:
/*
Author:王连霞
date:2018-11-15
version:1.0
desciption:电话号码对应的字符组合:
在电话或者手机上,一个数字如2对应着字母ABC,7对应着PQRS。
那么数字串27所对应的字符的可能组合就有3*4=12种(如AP,BR等)。
现在输入一个3到11位长的电话号码,
请打印出这个电话号码所对应的字符的所有可能组合和组合数。
*/
#include<iostream>
using namespace std;
char*letter[10]={"","","ABC","DEF","GHI","JKL","MNO","PQRS","TUV","WXYZ"}; //存放每个数字对应的字母
int num[10]={0,0,3,3,3,3,3,4,3,4}; //表示0-9对应字母的个数
char input[15];
char output[15];
void RS(int t,int length) //递归函数
{
if(t == length) //递归出口,当输入的是一个数字时,返回这个数字所有可能性的组合
{
cout<<output<<endl;
}
for(int i=0; i<num[input[t]]; i++) //递归体,输入一串数字,每个数字代表不同的字符串,返回最后一个数字跟前面已产生的字符串进行组合
{
output[t] = letter[input[t]][i];
RS(t+1,length);
}
}
int main()
{
int length;
printf("输入一个3到11位长的电话号码:");
scanf("%s",input);
printf("该电话号码所对应字符的所有可能的组合是:\n");
length = strlen(input);
int total = 1;
for(int i=0; i<length; i++)
{
input[i] -= '0';
total *= num[input[i]];
}
RS(0,length);
cout<<"组合数:"<<total<<endl;
return 0;
}
(4)运行结果:
4.
4.日本著名数学游戏专家中村义作教授提出这样一个问题:父亲将2520个桔子分给六个儿子。分完 后父亲说:“老大将分给你的桔子的1/8给老二;老二拿到后连同原先的桔子分1/7给老三;老三拿到后连同原先的桔子分1/6给老四;老四拿到后连同原先的桔子分1/5给老五;老五拿到后连同原先的桔子分1/4给老六;老六拿到后连同原先的桔子分1/3给老大”。结果大家手中的桔子正好一样多。问六兄弟原来手中各有多少桔子?
(1)题目分析
每个儿子的橘子数目有两种,原有的和现有的,除了老大,其他的儿子原有的+别人给的-给别人的=平均数,所以原有的=现有的+给别人的-别人给的。
大儿子得到六儿子之前的是:大儿子原有的-给二儿子的(1/8)=现有的-别人给的;
六儿子现有的(ave)=(六儿子原有的+别人给的)(2/3),所以,( 7/8大儿子原有的)=现有的-六儿子给的,所以大儿子现有的=得到六儿子之前的8/7倍。
(2)算法构造
//c[i][0]表示第i个儿子分出去桔子的总数,c[i][1]表示第i个儿子从父亲出得到桔子的总数
c[i][1] = (ave - ave /2)*(8 - i) / (8- 1 - i);
c[i][0] =c[i][1] - (ave- ave / 2); (i=0)
c[i][1] = ave*(8 - i) / (8 - 1 - i)-orange(c, i - 1);
c[i][0] = c[i][1] +orange(c, i - 1) - ave; (0<i<6)
(3)代码实现:
/*
Author:王连霞
date:2018-11-15
version:1.0
desciption:日本著名数学游戏专家中村义作教授提出这样一个问题:
父亲将2520个桔子分给六个儿子。分完
后父亲说:
"老大将分给你的桔子的1/8给老二;
老二拿到后连同原先的桔子分1/7给老三;
老三拿到后连同原先的桔子分1/6给老四;
老四拿到后连同原先的桔子分1/5给老五;
老五拿到后连同原先的桔子分1/4给老六;
老六拿到后连同原先的桔子分1/3给老大"。
结果大家手中的桔子正好一样多。问
六兄弟原来手中各有多少桔子?
*/
#include<iostream>
using namespace std;
int c[5][2] = { {0,0},{ 0,0 },{ 0,0 },{ 0,0},{ 0,0 } };
int orange(int c[5][2], int i)
{ int ave = 420;
if (i == 0) //递归出口
{
//c[i][0]表示第i个儿子分出去桔子的总数,c[i][1]表示第i个儿子从父亲出得到桔子的总数
//第一个儿子从父亲那里得到桔子数为:平均数减去最后一个孩子分出去的部分后乘以8/7
c[i][1]= (ave - ave /2)*(8 - i) / (8- 1 - i);
c[i][0]= c[i][1] - (ave- ave / 2); //第一个孩子分给第二个孩子的桔子数量
}
else //递归体
{
c[i][1]= ave*(8 - i) / (8 - 1 - i) - orange(c, i - 1);//第i个儿子从父亲那里得到桔子总数
c[i][0] = c[i][1] + orange(c, i - 1) - ave;//第i个儿子分给下一个儿子的橘子数量
}
return c[i][0];
}
void main()
{
orange(c,5);
cout<<"父亲最初分配桔子情况如下"<<endl;
for (int i = 0; i<=5; i++)
{
cout<<"原来第"<<i+1<<"个儿子从父亲那里得到"<<c[i][1]<<"个桔子"<<endl;
}
for ( i = 0; i<=5; i++)
{
cout<<"第"<<i+1<<"个儿子向下一个儿子分出"<<c[i][0]<<"个桔子"<<endl;
}
}
(4)运行结果: