C语言系列1--求小球弹跳高度

C语言系列1–求小球弹跳高度

我是编程小白,记录自己c语言想法的一天。今天在做关于c的一道简单题的时候,遇到的问题。题目描述如下:

一球从M米高度自由下落,每次落地后返回原高度的一半,再落下。 它在第N次落地时反弹多高?共经过多少米? 保留两位小数

  • 输入格式
    M N
  • 输出格式
    它在第N次落地时反弹多高?共经过多少米? 保留两位小数,空格隔开,放在一行。
    • 样例输入一:
      1000 5
    • 输出:
      31.25 2875.00

下面是我个人第一次进行测试的代码,这段代码知识通过了一半的测试样例,并未完全通过。错误地方我会进行解释。代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>
#include<string.h>
#include<windows.h>
#include<corecrt_math.h>
//上面这些是一些简单的包。
int main()
{
	int n,i;//这里的n表示输入小球的弹跳次数,i是循环的标记变量
    double  m, sum=0,a1;//a1代表落地后反弹多少米,m是记录每次小球落地后跳起来多高的变量。
    scanf("%lf %d",&m,&n);
    for (i = 1; i <= n; i++)
    {
        /*if (i == 1)
        {
            sum = sum + m;
        }
        else
        {
            sum = sum + m * 2.0;
        }*/
        //这里正段注释的内容主要是进行统计小球总共走了多少米,也就是说,从放手落地到弹起5次后,但是上面这段代码有个小小的BUG。
    	//下面的这两个代码的主要意思是为了计算小球落地一次后,再次弹起它的高度有多少。
        a1 = m / 2.0;
        //printf("%lf\n",a1);
        m = a1;
    }
    //printf("********************");
    printf("%5.2lf %5.2lf",a1,sum);
    return 0;
}

讲解:

为了可以理解我花了一个简单的草图,(鼠标画的,有点乱,凑活理解一下)
在这里插入图片描述

这里从手放下的时候是100米,第一次触底再弹起的时候是50米,然后会向下落去,这样就还会走50米的距离。也就是说在触底第二次的时候,小球走了100米+50米(上升的)+50米(下降的)。第三次的时候,道理也是一样的100米+50米(上升的)+50米(下降的)+25米(上升)+25米(下降)。所以第一次我的编程逻辑就是先算小球弹跳起来后是多少,题目中给出了限制条件:为原来的一半。
在这里插入图片描述

所以m是小球初始高度(假设100米),当for循环中i=1的时候,m也还是100米,然后m进行减半操作,这里为什么除以2.0而不是2的原因可以去看看取整取余操作限制。然后得到了a1,这里的a1也就是经过落地一次后,小球的高度位置(假设为50米)。然后将这次的位置重新赋值给m。就相当与重新给m赋初始值让小球从50米的距离落地一般。然后循环进行i++,这里的i记录的是小球落地的次数。这两行代码的意思较为简单。重点在于统计小球一共走过了多少米的路径有了一点点的困难。

这里可以回过头去看看我第一次的代码内容(也就是那个错误的代码)。我写下了一个if判断条件,我在想如果小球从第一次落地后,后面进行的都是减半操作的双路径,那么我可不可以将从放手到第一次落地的路径单独拿出来进行计算,这样后面进行累加的时候可以简单一点。
在这里插入图片描述
i==1的意思就是截至第一次落地,小球一共走了100米,然后如果i不是第一次落地后,那么我就对m进行累加,m*2.0的意思也就是上升和下降的总路径数。然后最后进行输出即可。但是在测试的时候出现了一个错误。我忽略了一个很严重的问题:我只是将第一次落地之前的100米单独拿出来了,并没有考虑到第一次落地后,小球还会起跳,而这个起跳高度,是50米,也就是说:“小球第一次落地后,总路径数是150米,而不是100米”,也就是说如果输入样例是这样的时候,我的代码是不能通过的:
输入样例
100 1
输出答案
150
这个细节问题让我的测试样例没有通过。我对代码进行了修改。

修改后的代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>
#include<string.h>
#include<windows.h>
#include<corecrt_math.h>
//上面这些是一些简单的包。
int main()
{
	int n,i,flag=0;//flag是一个标记变量,初始值是0,在代码中想要改变的时候进行flag=1的操作
	double  m, sum=0,a1;
	scanf("%lf %d",&m,&n);
	for (i = 1; i <= n; i++)
	{
		if (i == 1)
		{
			sum = sum + m ;
			if (i == n)   //这里加入i==n的判断就是为了防止如果测试用例输入1的时候的特殊情况
			{
				sum = sum + m / 2;//这里sum如果用数字来代替的话就是sum=100+50,前面的100是上面if(i==1)的时候的100
				//即单独从放手到落地没弹起的路径,然后这里第二个if(i==n)表达的是关于如果输入的测试样例是100 1这样的特殊样例的时候进行的判断。
				printf("%.2lf %.2lf", m / 2.0, sum);//这里的m/2.0的意思就是第一次落地后弹起来的高度
				flag = 1;//这里的flag=1的主要作用就是我即然以及输出了最后的答案,就直接跳出这个大的for循环,不用进行后面的过程语句。但是这里输出后,循环语句外面还有一个输出,所以在外面的输出语句外面加一个判断,判断flag是不是0,0就代表没有进入到刚刚那个i==n的判断中,正常输出即可。否则就输出语句就是循环内的语句。
				break;	
			}
		}
		else
		{
			sum = sum + m * 2.0;
		}
		a1 = m / 2.0;
		m = a1;
	}
	if(flag==0)
	{ 
		printf("%.2lf %.2lf",a1,sum);
	}
	return 0;
}

到此,这道题才算解决完毕。这道题结束后,我也看了其他大神写的解答,他们的更加完善和巧妙,继续学习。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

树懒兜兜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值