课后作业:过程的封装:函数(上)
计算谐均值
任务描述
两数值的谐均值可以这样计算:首先对两数值的倒数取平均值,最后再取倒数。编写一个带有两个double参数的函数,计算这两个参数的谐均值。函数原型为: double Calculate(double x,double y);
例如,当$x=3,y=4$时,则谐均值的为 $1/((1/x+1/y)/2) = 3.429$
编程要求
根据提示,补全函数,并返回输入值的谐均值。
测试说明
平台会对你编写的代码进行测试,先输入测试样例数t,然后输入t组输入,程序依次输出t个谐均值。
测试输入:
1
3 4
预期输出:
3.429
测试输入:
2
3 4
6.5 3.8
预期输出:
3.429
4.796
参考代码
#include <iostream>
#include <iomanip>
using namespace std;
double Calculate(double x,double y)
{
// write your code here
return 2/(1/x+1/y);
}
// 请不要修改main函数
int main()
{
int t;
cin >> t;
while (t--) {
double x, y;
cin >> x >> y;
cout << fixed << setprecision(3) << Calculate(x,y) << endl;
}
return 0;
}
进制转换
任务描述
输入两个十进制正整数 n 和 base($2\leq base\leq16$),将 n 转换为 base 进制后输出。
相关知识
为了完成本关任务,你需要掌握:1.如何将十进制数转换成 base 进制数。
进制转换
思考十进制向二进制转换的方法:除2取余,那么将十进制数转换成 base 进制数只需要重复“除base取余”。
大于十进制的 base 进制常用的是十六进制,在十六进制中,除了十进制中用到的 0-9 这十个数字外,还引入了A、B、C、D、E、F 来分别表示十进制的10、11、12、13、14、15.
编程要求
定义并调用函数 printInt(n,base),它的功能是输出 n 的 base 进制
测试说明
平台会对你编写的代码进行测试:
测试输入:255 16;
预期输出:
FF
测试输入:128 2;
预期输出:
10000000
提示:可以利用A、B、C、D、E、F 来分别表示十进制中的10、11、12、13、14、15.
参考代码
#include<iostream>
using namespace std;
const int MAX = 1000;
void printInt(int n,int base)
{
// write your code here
static char num[20] = "0123456789ABCDEF";
int a[MAX];
for (a[0]=0; n; n/=base) a[++a[0]] = n%base;
for (;a[0];) cout << num[a[a[0]--]];
}
int main()
{
int n, base;
cin >> n >> base;
printInt(n, base);
return 0;
}
摘苹果
任务描述
陶陶家的院子里有一棵苹果树,每到秋天树上就会结出 n ($1 \le n \le 100$) 个苹果。苹果成熟的时候,陶陶就会跑去摘苹果。陶陶有个 30cm 高的板凳,当他不能直接用手摘到苹果的时候,就会踩到板凳上再试试。
现在已知每个苹果到地面的高度 a[i] cm($1\le i \le n$,$100 \le a[i]\le 200$),以及陶陶把手伸直时能达到的最大高度 height cm ($100 \le height \le 120$),请你编写程序帮助陶陶计算一下他能摘到的苹果数目。
假设只要他能够伸手碰到苹果,苹果就会掉下来。
编程要求
调用函数 int GetApple(int a[], int height, int n)来计算淘淘能摘到的苹果数目。
函数参数:数组 a 保存苹果到地面的高度,height 代表陶陶把手伸直时能达到的最大高度,n为树上总的苹果数。
函数返回值:淘淘能摘到的苹果数目
测试说明
平台会对你编写的代码进行测试:
测试输入:
10
100 200 150 140 129 134 167 198 200 111
110
预期输出:
5
说明:第一行输入的数据是苹果数目n;第二行输入的数据是这n个苹果,每个苹果到地面的高度;第三行输入的数据是陶陶把手伸直时能达到的最大高度。
参考代码
#include<iostream>
using namespace std;
int GetApple(int a[], int height, int n)
{
int ans = 0;
for (int i=1;i<=n;i++) if (height + 30 >= a[i]) ans++;
return ans;
}
int main()
{
int n, height, *a;
cin >> n;
a = new int[n+1];
for (int i=1;i<=n;i++) cin >> a[i];
cin >> height;
cout << GetApple(a, height, n) << endl;
delete [] a;
return 0;
}
魔术师猜数
任务描述
在一种室内互动游戏中,魔术师要每位观众心里想一个三位数abc(a、b、c分别是百位、十位和个位数字),然后魔术师让观众心中记下acb、bac、bca、cab、cba五个数以及这5个数的和值。只要观众说出这个和是多少,则魔术师一定能猜出观众心里想的原数abc是多少。例如,观众甲说他计算的和值是1999,则魔术师立即说出他想的数是443,而观众乙说他计算的和值是1998,则魔术师说:“你算错了!”。请编程模拟这个数字魔术游戏。要求用函数实现,函数原型为:int Magic(int m); 其中形参m代表观众计算的和值。
编程要求
补全Magic函数,如果观众计算错误,请返回-1。另外请不要修改main函数。
测试说明
平台会对你编写的代码进行测试。测试数据包含t+1行,第一行是测试次数t,随后t行中每行输入一个m值,程序需要计算输出t个结果。
测试输入:
1
1999
预期输出:
The number is 443
测试输入:
2
1999
1998
预期输出:
The number is 443
The sum you calculated is wrong!
参考代码
思路
假设该数是 $x=100a+10b+c$,则 $m + x = 222(a+b+c)$。因此 $x \equiv -m \mod 222$。
代码
#include <iostream>
using namespace std;
int Magic(int m){
/***********begin************/
for (int x = 222-m%222; x < 1000; x += 222) {
if (222*(x/100+x/10%10+x%10) == m + x) return x;
}
return -1;
/***********end**************/
}
int main()
{
int t,m;
cin >> t;
while(t--){
cin >> m;
int res = Magic(m);
if(res == -1) {
cout << "The sum you calculated is wrong!\n";
} else {
cout << "The number is " << res << endl;
}
}
}
Fibonacci函数(附加题,选做)
任务描述
本关任务:设计函数fib,每调用一次就返回Fibonacci数列的下一个值,即第一次调用返回1,第二次调用返回1,第三次调用返回2,第四次调用返回3……
要求:不得使用全局变量。
编程要求
根据提示,在右侧编辑器补充代码,编写一个函数fib(),使结果符合要求。
测试说明
平台会对你编写的代码进行测试:
测试输入:无;
预期输出:
1
1
2
3
5
8
13
21
34
55
注意
此题在后台会人工重新评判,请各位严格按照题目要求编写。
参考代码
#include<iostream>
using namespace std;
int fib()
{
//write your code here
static int a = 1, b = 0;
int c = a + b;
b = a, a = c;
return b;
}
int main()
{
for (int i = 0; i < 10; i++)
cout << fib() << endl;
return 0;
}
潜泳问题(附加题,选做)
任务描述
某单位在某个湖里举行潜水比赛,这是一个团体项目,每一支队伍由n人组成,要求所有队员从A岸潜水到B岸。在潜水过程中必须用氧气瓶,但每支队伍只有一个氧气瓶。最多两个人同时使用一个氧气瓶,但此时两人必须同步前进,因此到达终点的时间等于较慢的一人单独从A到B的时间。大家都很Nice,随便两个人都愿意共用一个氧气瓶有用。请安排一种策略,让最后一名队员尽早到达终点。
编程要求
编写程序,首先输入队伍人数n(1 <= n <= 1000),接着是n个队员单独游到终点所用的时间。要求输出所有队员最早到达终点的时间。
测试说明
平台会对你编写的代码进行测试:
测试输入:
3
1
3
4
预期输出:
8
提示
简单来说,每个阶段运两个人过去有两种贪心原则:
- 用耗时最少的每次运一个走,
- 用耗时最少的和次少的分两次次运走耗时最多的两个走。
每次在两种贪心原则中,选择最优的。这道题的策略就是两种贪心优中选优。
具体做法: 实现排序函数。 首先将n各队员游到重点耗时长短按递增排序,得到 $P_1\ P_2\ …\ P_n$。 我们把A岸耗时最长的两个人$P_n, P_{n-1}$游到B岸看成一个步骤。为了达到耗时最短,需要在如下两种方案中选择。
方案1:安排耗时最短的两个人$P_1, P_2$先游到B岸,然后$P_1$游回A岸,接着安排耗时最长的两个人$P_n,P_{n-1}$游到B岸,再安排$P_2$游回A岸,总耗时$t_1 = 2*P_2 + P_1 + P_n$.
方案2:安排耗时最短和最长的$P_1,P_n$先游到B岸,$P_n$留在B岸,$P_1$回A岸。然后$P_1,P_{n-1}$游到B岸,再安排$P_1$游回A岸。总时间为$t_2 = 2*P_1 + P_n + P_{n-1}$,
如果$t_1 < t_2$,就选择方案一,否则方案二。重复上述策略,直到所有人到达B。算法实现时需要考虑人数。如果是奇数,最后在A岸剩下人为$P_1, P_2,P_3$,3人到达B岸耗时$P_1 + P_2 +P_3$;如果是偶数,最后剩下两人为$P_1,P_2$,耗时$P_2$。
一知道在哪儿,世界就变得像一张地图那么小了;不知道在哪儿,感觉世界才广阔。 ——《三体》
参考代码
#include <iostream>
using namespace std;
void sort(int a[], int n)
{
// sort a[]
// write your code here
for (int i=1;i<=n;i++)
for (int j=1,tmp;j<=n-i;j++) if (a[j]>a[j+1])
tmp = a[j], a[j] = a[j+1], a[j+1] = tmp;
}
int main()
{
// write your code here
int n; cin >> n;
int * a = new int [n+1];
for (int i=1;i<=n;i++) cin >> a[i];
sort(a, n);
int ans = 0;
for (int i=n;i>1;i-=2) {
if (i == 2) ans += a[2];
else if (i == 3) ans += a[1]+a[2]+a[3];
else if (2*a[2]+a[1]+a[i] < 2*a[1]+a[i]+a[i-1])
ans += 2*a[2]+a[1]+a[i];
else ans += 2*a[1]+a[i]+a[i-1];
}
cout << ans << endl;
return 0;
}