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;
}
到此,这道题才算解决完毕。这道题结束后,我也看了其他大神写的解答,他们的更加完善和巧妙,继续学习。