问题描述
财务处的小胡老师最近就在考虑一个问题:如果每个老师的工资额都知道,最少需要准备多少张人民币,才能在给每位老师发工资的时候都不用老师找零呢?
这里假设老师的工资都是正整数,单位元,人民币一共有100元、50元、10元、5元、2元和1元六种。
输入
输入数据包含多个测试实例,每个测试实例的第一行是一个整数n(n<100),表示老师的人数,然后是n个老师的工资。n=0表示输入的结束,不做处理。
输出
对于每个测试实例输出一个整数x,表示至少需要准备的人民币张数。每个输出占一行。
输入样例
3
1 2 3
0
输出样例
4
刚开始做本题的时候想到的是最笨的方法 …
定义一个算张数的函数,怎么算的呢?连循环都没想到,把每种币值的张数都算出来,然后再加起来。现在回想起来感觉这种方法不要太麻烦。
代码如下:
//version1
#include<stdio.h>
int snum(int sly)
{
int cnt = 0;
int hdnum, ftnum, tennum, fnum, tnum,onum;
hdnum = sly / 100;
ftnum = (sly - hdnum * 100) / 50;
tennum = (sly - hdnum * 100 - ftnum * 50)/10;
fnum = (sly - hdnum * 100 - ftnum * 50 - tennum * 10) / 5;
tnum = (sly - hdnum * 100 - ftnum * 50 - tennum * 10 - fnum * 5) / 2;
onum = (sly - hdnum * 100 - ftnum * 50 - tennum * 10 - fnum * 5 - tnum * 2) / 1;
cnt = hdnum + ftnum + tennum + fnum + tnum + onum;
return cnt;
}
int main(void)
{
int n, sly;
int cnt = 0;
while (scanf_s("%d", &n) != EOF) {
if (n == 0)
break;
for (int i = 1; i <= n; i++) {
scanf_s("%d", &sly); // 读取一个人的工资
cnt += snum(sly); // 算出这个人工资对应张数的最小值
}
printf_s("%d\n", cnt);
cnt = 0;
}
return 0;
}
考虑到这段代码实在是有点啰嗦,在苦思冥想之后终于想到优化方法,声明一个int数组用来储存币值,然后使用for循环来算出张数。
代码如下:
#include<stdio.h>
int main(void)
{
int n, sly, cnt;
int worth[] = { 100,50,10,5,2,1 };
while (scanf_s("%d", &n) != EOF) {
if (n == 0)
break;
cnt = 0;
for (int i = 1; i <= n; i++) {
scanf_s("%d", &sly);
for (int j = 0; j < SIZE; j++) {
cnt += sly / worth[j]; //计算张数
sly %= worth[j]; //去除掉已经计算过张数的币值
}
}
printf_s("%d\n", cnt);
}
return 0;
}
是不是清爽多了呢,嘿嘿
但是突然想到在我们的日常生活中,我们很少使用到二元面值的钞票,由此又引发一个问题,如果想要改变币值的话,不仅需要修改数组的元素,还需要修改数组大小。我们知道在C语言中,若初始化数组时省略方括号中的数字,编译器会根据初始化列表中的项数来确定数组大小。但是在计算张数的时候需用到for循环,条件与数组大小有关。可不可以让程序自己来做呢?答案是可以
代码如下:
#include<stdio.h>
int main(void)
{
int n, sly, cnt;
int worth[] = { 100,50,10,5,2,1 };
int size = sizeof(worth) / sizeof(int); //计算数组大小
while (scanf_s("%d", &n) != EOF) {
if (n == 0)
break;
cnt = 0;
for (int i = 1; i <= n; i++) {
scanf_s("%d", &sly);
for (int j = 0; j < size; j++) {
cnt += sly / worth[j];
sly %= worth[j];
}
}
printf_s("%d\n", cnt);
}
return 0;
}