Jasin Yip

计蒜客【挑战难题】系列讲解(六)泥塑课

题目

第6题:泥塑课

  小米是一个幼儿园老师,每学期的泥塑课上,她都会给每个学生发不超过250立方厘米的等量橡皮泥,教大家做泥塑。在上课过程中,她发现每个班都恰好有一个小朋友会去抢另一个小朋友的橡皮泥,于是她决定,在正式开始做泥塑前,让大家把手里的橡皮泥都捏成一个立方体,并且测量手里捏好的橡皮泥的长、宽和高。这样,她就可以知道谁被谁抢了橡皮泥了。
  小米老师在不同的学期可能会带一个班或者同时带多个班,因此输入数据可能有一组或者多组。每组输入数据的第一行为一个整数n,表示了这个班的小朋友数,之后n行每行包括了由空格分隔的三个整数和一个字符串,那个字符串表示了小朋友的名字,前面三个整数则是这个学术手里橡皮泥块的长、宽、高数据。按照幼儿园的规定,每个班最多有9个小朋友,最少也要有2个小朋友,每个小朋友在学籍系统中的名称不超过8个字符长。当出现一个班级的小朋友数为-1时,表示没有更多的班级了。
输出行数与小米老师带的班级数相同,形式为“X took clay from Y.”,具体请参考样例输出。

样例输入

10 10 2 Jill
5 3 10 Will
5 5 10 Bill
4
2 4 10 Cam
4 3 7 Sam
8 11 1 Graham
6 2 7 Pam
-1

样例输出

Bill took clay from Will.
Graham took clay from Cam.

C 实现

#include <stdio.h>
#define NUM_OF_CLASSROOM 20    //设定课室数组上限
int main(){
  //初始化课室数量,内容为每个课室的人数,amountClass表示课室的数量
  int numOfStudent[NUM_OF_CLASSROOM] = { 0 }, amountClass = 0;  

  //记录学生姓名指针的二维数组,
  //首位为课室号,次位为学生学号(由0开始计),末位表示最长为8个字符。
  //调用例:&name[2][3]可得到班别为2,学号为3的同学的姓名 
  char name[NUM_OF_CLASSROOM][9][9];    

  int V[NUM_OF_CLASSROOM][9];    //记录每个学生所拥有泥塑的体积
  int i, j;
  int x, y, z;  //长x宽y高z,用以计算体积
  int max, min; //某课室中拥有泥塑体积最大max及最小min的学号

  //输入数据 
  scanf("%d", &numOfStudent[0]);
  while (numOfStudent[amountClass] != -1){
    for (i = 0; i < numOfStudent[amountClass]; i++){
      scanf("%d %d %d %s", &x, &y, &z, &name[amountClass][i]);
      //算出该班所有学生所拥有的泥塑体积
      V[amountClass][i] = x * y * z;    
    }
    scanf("%d", &numOfStudent[++amountClass]);
  }

  //找出每间课室拥有泥塑体积最大和最小的学生,并输出
  for (i = 0; i < amountClass; i++){
    min = max = 0;
    for (j = 0; j < numOfStudent[i]; j++){
      if (V[i][max] < V[i][j])
      max = j;
      if (V[i][min] > V[i][j])
      min = j;
    }
    printf("%s took clay from %s.", &name[i][max], &name[i][min]);
    if (i != amountClass - 1)
      printf("\n");
  }

  return 0;
}

它如何工作

输入部分

  输入部分使用while语句和for语句嵌套,while语句和for语句虽然都是循环,但在应用场景上略有不同,while语句更适合于循环次数不确定的情况,而for语句适合循环次数确定的情况。
  在输入的同时,应该马上算出该班该学生的体积,以免再来一个循环去计算,因为泥塑的长宽高是不重要的,体积才是我们要的东西。
  在while语句里面的scanf()函数里,我使用了 ++amountClass 这种称为“前置自增”的方式,与 amountClass++ 这样的后置自增方式不同,前置自增是在语句执行前首先自增,再去执行所在的语句,而后置自增的方式则是在语句执行完毕后再自增的。在当前的情况下,适宜使用前置自增。

处理并输出部分

  首先用for语句遍历所有课室,然后查看该课室每个学生所拥有的泥塑体积,找出拥有泥塑体积最大和最小的同学(因为其他同学的体积都是相等的),找出最大最小后,按照指定的格式输出对应的名字则可。

如有不懂,欢迎加入计蒜客QQ群咨询:

一群:239266679(满)
二群:228348940(满)
三群:159642279
四群:385386446

标签:c语言, 计蒜客, 挑战难题

已有 8 条评论

  1. Coco Coco

    学习!

  2. thx!很详细的讲解。
    样例输入 中应该是少了第一行 3 吧。

  3. Richard Richard

    为什么不用结构体?
    student {
    int x,y,h,V;
    string name;
    }

  4. moxienianhau moxienianhau

    谢谢 很仔细,有一个问题:就是那个name[NUM_OF_CLASSROOM][9][9]是一个三维数组,后来是怎么就用了name[i][j]了 变成2维数组了,不太懂 还有那个最后输出 去掉“&”结果也对 求大神指教

    1. 这是二维数组,首位为课室号,次位为学生学号(由0开始计),末位表示最长为8个字符。

  5. Mashimaro Mashimaro

    讲的很仔细,容易理解。

    1. 谢谢支持,欢迎常来浏览

      1. 小白奇 小白奇

        大神 能加你为好友嘛?

添加新评论