C语言程序设计精髓(MOOC第7周 )题

第7周练兵区编程题


NOTE:

  • 尾递归:当递归调用是整个函数体中最后执行的语句且它的返回值不属于任何表达式的一部分(即在回归阶段不需要任何计算)时,这种递归调用就是尾递归。尾递归的精髓就是 通过参数传递结果,达到不压栈的目的
  • 变量的作用域是指变量的作用范围,即在程序中可以被读写访问的区域,它取决于变量被定义的位置。
  • 形参也是局部变量,形参变量和实参变量的作用域是不同的,因此形参变量和实参变量同名时,二者互不干扰。
  • 只要同名的变量出现在不同的作用域内,二者互不干扰,编译器有能力区分不同作用域中的同名变量。
  • 变量的存储类型决定变量的生存周期—静态存储区中的变量生存期是整个程序,类似于学校的宿舍;动态存储区中的变量生存期是定义它的语句块,类似于外面的酒店宾馆。
  • extern int i; //声明,不是定义

  • int i; //声明,也是定义

经典递归算法题—汉诺塔问题

汉诺塔问题是指:一
块板上有三根针 A、B、C。A 针上套有 64 个大小不等的圆盘,按照大的在下、小的在上的顺序排列,要把这 64 个圆盘从 A 针移动到 C 针上,每次只能移动一个圆盘,移动过程可以借助 B 针。但在任何时候,任何针上的圆盘都必须保持大盘在下,小盘在上。从键盘输入需移动的圆盘个数,给出移动的过程。

算法思想:

对于汉诺塔问题,当只移动一个圆盘时,直接将圆盘从 A 针移动到 C 针。若移动的圆盘为 n(n>1),则分成几步走:把 (n-1) 个圆盘从 A 针移动到 B 针(借助 C 针);A 针上的最后一个圆盘移动到 C 针;B 针上的 (n-1) 个圆盘移动到 C 针(借助 A 针)。每做一遍,移动的圆盘少一个,逐次递减,最后当 n 为 1 时,完成整个移动过程。

程序代码:
#include<stdio.h>
void move(char a,char b) //移动函数,从a移到b
{
    static int k = 1;
    printf("%2d: %c ---> %c\n",k,a,b);
    k++;
}

void hanoit(int n,char a,char b,char c)//递归函数
{
    if(n == 1)move(a,c);
    else
    {
        hanoit(n - 1,a,c,b);
        move(a,c);
        hanoit(n - 1,b,a,c);
    }
}

int main()
{
    int n;
    scanf("%d",&n);;
    hanoit(n,'A','B','C');
    return 0;
}

1. 谐均值计算

题目内容:
两数值的谐均值可以这样计算:首先对两数值的倒数取平均值,最后再取倒数。编写一个带有两个double参数的函数,计算这两个参数的谐均值。

函数原型为: double Calculate(double x,double y);

#include <stdio.h>
double Calculate(double x,double y);
int main()
{
    double x,y;
    printf("Input two doubles:\n");
    scanf("%lf%lf",&x,&y);
    printf("1/((1/x+1/y)/2) = %0.3f\n",Calculate(x,y));
    return 0;
}

double Calculate(double x,double y)
{
    return 1/((1/x+1/y)/2);
}

2. 输出指定行列数的字符

题目内容:
编写一个函数,函数原型: void Chline(char ch, int column, int row);
该函数的3个参数是一个字符和两个整数。字符参数是需要输出的字符。第一个整数说明了在每行中该字符输出的个数,而第二个整数指的是需要输出的行数。编写一个调用该函数的程序。

#include <stdio.h>
void Chline(char ch, int column, int row);
int main()
{
    char ch;
    int co,row;
    printf("input a char:\n");
    scanf("%c",&ch);
    printf("input column and row:\n");
    scanf("%d%d",&co,&row);
    Chline(ch,co,row);
    return 0;
}

void Chline(char ch, int column, int row)
{
    int i,j;
    for(i = 0;i < row; i++)
    {
        for(j = 0;j < column; j++)
        {
            printf("%c",ch);
        }
        printf("\n");
    }
}

3. 魔术师猜数

题目内容:
在一种室内互动游戏中,魔术师要每位观众心里想一个三位数abc(a、b、c分别是百位、十位和个位数字),然后魔术师让观众心中记下acb、bac、bca、cab、cba五个数以及这5个数的和值。只要观众说出这个和是多少,则魔术师一定能猜出观众心里想的原数abc是多少。例如,观众甲说他计算的和值是1999,则魔术师立即说出他想的数是443,而观众乙说他计算的和值是1998,则魔术师说:“你算错了!”。请编程模拟这个数字魔术游戏,要求用函数实现。

函数原型为: int Magic(int m);

#include <stdio.h>
int Magic(int m);
int main()
{
    int n;
    scanf("%d",&n);
    if(Magic(n) == 0)
        printf("The sum you calculated is wrong!\n");
    else
        printf("The number is %d\n",Magic(n));
    return 0;
}

int Magic(int m)
{
    int a, b, c, i, sum;


    for(i = 100;i <= 999; i++)
    {
        c = i%10;
        b = (i/10)%10;
        a = i/100;
        sum = 122*a + 212*b + 221*c;
        if(m == sum)
            return i;
    }
    return 0;
}

4. 计算礼炮声响次数

题目内容:
在海军节开幕式上,有A、B、C三艘军舰要同时开始鸣放礼炮各21响。已知A舰每隔5秒放1次,B舰每隔6秒放1次,C舰每隔7秒放1次。假设各炮手对时间的掌握非常准确,请编程计算观众总共可以听到几次礼炮声。

#include <stdio.h>
int main()
{
    int cnt = 0;
    int t;
    for(t = 0; t <= 140; t++)
    {
        if(t%5 == 0&& t <= 5*20)
        {
            cnt++;
            continue;
        }
        if(t%6 == 0&& t <= 6*20)
        {
            cnt++;
            continue;
        }
        if(t%7 == 0)
        {
            cnt++;
        }
    }
    printf("n=%d",cnt);
    return 0;
}

5. 水手分椰子

题目内容:
n(1<n<=5)个水手在岛上发现一堆椰子,先由第1个水手把椰子分为等量的n堆,还剩下1个给了猴子,自己藏起1堆。然后,第2个水手把剩下的n-1堆混合后重新分为等量的n堆,还剩下1个给了猴子,自己藏起1堆。以后第3、4个水手依次按此方法处理。最后,第n个水手把剩下的椰子分为等量的n堆后,同样剩下1个给了猴子。请用迭代法编程计算并输出原来这堆椰子至少有多少个,n的值要求从键盘输入。若输入的n值超出要求的范围,程序输出"Error!"。

提示: 分成的等量的堆数应该与水手的数量一致.

#include <stdio.h>
int coconut(int n);
int main()
{
    int n;
    printf( "Input n(1<n<=5):\n");
    scanf("%d",&n);
    printf("y=%d\n",coconut(n));
    return 0;
}

int coconut(int n)
{
    int i = 1;
    float x = 1,y;
    y = n * x + 1;
    do
    {
        y = y * n / (n - 1) + 1;
        i++;
        if(y!=(int)y)
        {
            x++;
            y = n * x + 1;
            i = 1;
        }
    }while(i < n);
    return (int)y;
}

6. 递归法计算游戏人员的年龄

题目内容:
题目内容:
有n个人围坐在一起,问第n个人多大年纪,他说比第n-1个人大2岁;问第n-1个人,他说比第n-2个人大2岁,…,问第3个人,他说比第2个人大2岁;问第2个人,他说比第1个人大2岁。第1个人说自己10岁,问第n个人多大年纪。

递归函数原型: unsigned int ComputeAge(unsigned int n);

#include <stdio.h>
unsigned int ComputeAge(unsigned int n);
int main()
{
    unsigned int n;
    scanf("%u",&n);
    printf("The person's age is %u\n",ComputeAge(n));
    return 0;
}

unsigned int ComputeAge(unsigned int n)
{
    if(n == 1)return 10;
    else
        return ComputeAge(n - 1) + 2;
}

7. 递归法计算两个数的最大公约数

题目内容:
利用最大公约数的性质计算。对正整数a和b,当a>b时,若a中含有与b相同的公约数,则a中去掉b后剩余的部分a-b中也应含有与b相同的公约数,对a-b和b计算公约数就相当于对a和b计算公约数。反复使用最大公约数的上述性质,直到a和b相等为止,这时,a或b就是它们的最大公约数。这三条性质,也可以表示为:

性质1 如果a>b,则a和b与a-b和b的最大公约数相同,即Gcd(a, b) = Gcd(a-b, b)

性质2 如果b>a,则a和b与a和b-a的最大公约数相同,即Gcd(a, b) = Gcd(a, b-a)

性质3 如果a=b,则a和b的最大公约数与a值和b值相同,即Gcd(a, b) = a = b

#include <stdio.h>
int Gcd(int a,int b);
int main()
{
    int a,b;
    printf("Input a,b:");
    scanf("%d,%d",&a,&b);
    if(Gcd(a,b) == 0)
        printf("Input error!\n");
    else
        printf("%d\n",Gcd(a,b));
    return 0;
}

int Gcd(int a,int b)
{
    if(a <= 0 || b <= 0)
        return 0;
    if(a == b)
        return a;
    else if(a > b)
        return Gcd(a - b,b);
    else
        return Gcd(a,b - a);
}

8. 寻找中位数v1.0

题目内容:
编写一个函数返回三个整数中的中间数。函数原型为: int mid(int a, int b, int c);
函数功能是 返回a,b,c三数中大小位于中间的那个数。

#include<stdio.h>
int mid(int a, int b, int c);
int main()
{
    int a,b,c;
    scanf("%d%d%d",&a,&b,&c);
    printf("The result is %d\n",mid(a,b,c));
    return 0;
}

int mid(int a, int b, int c)
{
    int low,temp1 = a<b?a:b;
    low = temp1 < c? temp1:c;
    int high ,temp2= a>b?a:b;
    high = temp2 > c?temp2:c;
    return a+b+c-low-high;
}

8. 还原算术表达式

题目内容:
编写程序求以下算式中XYZ的值,其中两数XYZ与YZZ相加的和n(99<n<1000)的值要求从键盘输入。

在这里插入图片描述

#include<stdio.h>
int main()
{
    int x,y,z,flag = 0;
    int n;
    printf("Input n(n<1000):\n");
    scanf("%d",&n);
    for(x = 1; x <= 9; x++)
    {
        if(flag == 0)
        for(y = 1; y <= 9; y++)
        {
            if((n - 100*x - 110*y)%12 == 0&&(n-100*x-110*y)/12 > 0)
            {

                printf("X=%d,Y=%d,Z=%d\n",x,y,(n-100*x-110*y)/12);
                flag = 1;
            }
        }
    }

    if(flag == 0)
        printf("Invalid\n");
    return 0;
}
  • 5
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值