编程练习 15.11.5~15.11.8



成绩统计(for lab)

程序设计期中考试结束后万老师需要统计学生的成绩,并为其分组,但万老师非常繁忙,因此把这项工作交给TA完成,TA需要编写一个允许输入多名同学成绩并将所有同学成绩的统计情况以表格形式打印的C语言程序。
输入:输入为多行,每一行包含一个成绩,成绩在0-100内为有效成绩(包含0和100),若成绩无效,打印”Input scores from 0 to 100”,输入以EOF结束
输出:所有同学成绩的分布情况表,格式如下:

注意:默认程序输入均为整数成绩。打印统计表格时,整数可以利用”%3d”。对齐均使用空格,没有用到制表符’\t’。
如:
printf(“——————————–\n”);
printf(“Total : %3d persons\n”, n);

读题

my answer

#include<stdio.h>
    int main() {
        int x;
        int a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0;
        int a5 = 0, a6 = 0, a7 = 0, a8 = 0, a9 = 0, a10 = 0;
        while (scanf("%d", &x) != EOF) {
        if (x < 0 || x > 100) {
            printf("Input scores from 0 to 100\n");
            return 0;
        } else {
           switch (x /= 10) {
            case 0: a0++;
                    break;
            case 1: a1++;
                    break;
            case 2: a2++;
                    break;
            case 3: a3++;
                    break;
            case 4: a4++;
                    break;
            case 5: a5++;
                    break;
            case 6: a6++;
                    break;
            case 7: a7++;
                    break;
            case 8: a8++;
                    break;
            case 9: a9++;
                    break;
            case 10: a10++;
                    break;
        }
        }
        }
     int sum = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10;
     printf("  0 <= x <  10 : %3d persons\n", a0);
     printf(" 10 <= x <  20 : %3d persons\n", a1);
     printf(" 20 <= x <  30 : %3d persons\n", a2);
     printf(" 30 <= x <  40 : %3d persons\n", a3);
     printf(" 40 <= x <  50 : %3d persons\n", a4);
     printf(" 50 <= x <  60 : %3d persons\n", a5);
     printf(" 60 <= x <  70 : %3d persons\n", a6);
     printf(" 70 <= x <  80 : %3d persons\n", a7);
     printf(" 80 <= x <  90 : %3d persons\n", a8);
     printf(" 90 <= x < 100 : %3d persons\n", a9);
     printf("       x = 100 : %3d persons\n", a10);
     printf("--------------------------------\n");
     printf("Total          : %3d persons\n", sum);
    return 0;
}

standard answer

#include <stdio.h>
#include <stdlib.h>
#define  N 11

int main() {

    int i, n, data, num[N];
    // Initialization of array
    for (i = 0; i < N; i++) {
        num[i] = 0;
    }
    n = 0;
    while (scanf("%d", &data) != EOF) {
        if (data < 0 || data > 100) {
            printf("Input scores from 0 to 100\n");
            exit(1);
        } else {
            num[data/10]++;
            n++;
        }
    }
    // Show the distribution
    for (i = 0; i < N - 1; i++) {
    printf("%3d <= x < %3d : %3d persons\n", i * 10, (i + 1) * 10, [i]);
    }
    printf("       x = 100 : %3d persons\n", num[N - 1]);
    printf("--------------------------------\n");
    printf("Total          : %3d persons\n", n);
    return (0);
}

反馈

*1. 一旦输入的数不对,立刻输出 那句话 然后就结束程序了 所以在后面直接加上return
2. 当scanf 用 %d 取到错误的值的时候, 会返回错误值, 这时直接判断 相应的赋值的变量是不是EOF就可以知道什么时候结束(!= EOF 时执行)
3.在这里我第一次用了switch
switch(变量) {
case 变量的值: 语句;
break;
case ………..
}
3.参考答案用数组和循环简化了代码..不用写一长串*

simple digest(for lab)

Please digest the message,which contains n integer k(1 <= n <= 100; 0 <= integer <= 10000).
The digest rule:
1.First,you should get the mode according to the integer k.Use the getMode() method, you can get the mode.
2.You should map every integer k into the integer m. And then add them all.
If mode is equal to–>
0:m is euqal to k
1:m is euqal to encrypt 1 result. that means use encrypt_1() method to encrypt k.
2:m is euqal to encrypt 2 result. that means use encrypt_2() method to encrypt k.
3:m is equal to two encrypt method result’ sum.encrypt_1()+encrypt_2().
4:m is euqal to 2 * encrypt 1 result.
5:m is euqal to 2 * encrypt 2 result.
6,7….: m is equal to 2 * k.
Input format:
first line:n which stands for the integer number.
second line:n integer.
output format:
the sum of n integer after mapping + ‘\n’
For example:
[Input]
5
1 2 3 4 5
[Output]
107

已给出encrypt.h

#ifndef __ENCRYPT_H__
#define __ENCRYPT_H__
// 上述宏定义是为了防止encrypt.h被重复声明
// 如果已经引用了这个.h文件一次,__ENCRYPT_H__就已经定义过了
// 再次引用就会跳过这块内容,直到#ednif下方

int encrypt_1(int data);
int encrypt_2(int data);
int getMode(int data);

int getMode(int data) {
    return data % 10;
}

int encrypt_1(int data) {
    return data % 20;
}

int encrypt_2(int data) {
    return data % 20 + 20;
}

#endif

读题

当时真的看不懂什么鬼意思啊啊啊啊啊啊啊啊啊啊啊啊啊啊
嗯,题中的m即getmode函数使用后的返回值..
然后不同的m对应不同的对k的操作..

my answer

#include<stdio.h>
#include"encrypt.h"
int main() {
    int n, i, k, sum = 0;
    scanf("%d", &n);
    for (i = 0; i < n; i++) {
        scanf("%d", &k);
        int m = getMode(k);
        if (m == 0) {
          sum += k;
        } else if (m == 1) {
            sum += encrypt_1(k);
        } else if (m == 2) {
            sum += encrypt_2(k);
        } else if (m == 3) {
            sum += encrypt_1(k)+encrypt_2(k);
        } else if (m == 4) {
            sum += 2 * encrypt_1(k);
        } else if (m == 5) {
            sum += 2 * encrypt_2(k);
        } else if (m == 6 || m == 7 || m == 8 || m == 9) {
            sum += 2 * k;
        }
    }
    printf("%d\n", sum);
    return 0;
}

standard answer

#include <stdio.h>
#include "encrypt.h"

int main() {
    int mode, number;
    int n;
    int sum = 0;
    scanf("%d", &n);

    while (n--) {
        scanf("%d", &number);
        // 获取数据处理的模式
        mode = getMode(number);

        if (mode == 0) {
            sum += number;
        } else if (mode == 1) {
            sum += encrypt_1(number);
        } else if (mode == 2) {
            sum += encrypt_2(number);
        } else if (mode == 3) {
            sum += encrypt_1(number) + encrypt_2(number);
        } else if (mode == 4) {
            sum += 2 * encrypt_1(number);
        } else if (mode == 5) {
            sum += 2 * encrypt_2(number);
        } else {
            sum += 2 * number;
        }
    }

    printf("%d\n", sum);
}

反馈

*加密问题
1.引用 #include”头文件”
2. 判断符号是 == 啊啊啊啊不是 = 赋值符啊啊啊啊啊啊
3.自定义的函数貌似不可以直接作为一个值???
4.只处理一次的数用循环就好了不用数组*

路灯问题(for hw)

Description:
至二路口的新广场开张了,jeremy每天都要路过广场前的街道,这条街上有很多盏路灯。他发现这么一个现象:
灯的编号从0开始到m一共有m+1盏路灯,其中有不少灯都坏了。
通过不断地调查,jeremy得到了n条数据,每一条都用于表示坏了的灯,并且数据中的编号表示的是一整段的路灯都坏了。比如:
“200 201”代表的是编号200、201灯已坏,而
“100 105”代表的则是100、101、102、103、104、105全都坏了。
jeremy想知道现在一共还有几盏灯是好的,你能帮他解决这个问题嘛?
input:
1000 3
200 201
100 105
900 1000
output:
892
Hint:
利用数组存储,学习如何初始化数组等功能,比较简单当做预习吧。
范围:m<=10000
有任何问题请及时联系TA,由于题目放出来之后无法立即改动,所以请同学们发现有任何坑爹的地方请在评论区相互提醒,谢谢。

读题

一开始没懂1000 后面的3什么意思..后来发现代表下面有3条信息
明白之后就简单多了.
然而.
一开始我的做法是把信息里提到的都减掉
后来发现,会有重复的部分
所以要用数组来表示这一串灯,1/0表示灯的好坏
这样就不怕重复了~~~

my answer

#include<stdio.h>
int main() {
    int m, n, i, j, x, y;
    int a[10000] = {};
    scanf("%d%d", &m, &n);
    for (i = 0; i < n; i++) {
        scanf("%d%d", &x, &y);
        for (j = x; j <= y; j ++)
            a[j] = 1;
    }
    int broken = 0;
    for (i = 0; i <= m ; i++)
        broken += a[i];
    printf("%d", m + 1 - broken);
    return 0;
}

standard answer

#include<stdio.h>
int main() {
    int m, n;
    int light[10005] = {0};
    int i, j;
    int head, tail;
    scanf("%d", &m);
    for (i = 0; i <= m; i++)
        light[i] = 1;
    scanf("%d", &n);
    for (i = 0; i < n; i++) {
        scanf("%d %d", &head, &tail);
        for (j = head; j <= tail; j++) {
            light[j] = 0;
    }
    }
    int result = 0;
    for (i = 0; i <= m; i++)
        result += light[i];
    printf("%d", result);
    return 0;
}

反馈

最后一个是我
最后一个上榜的是我啊哈哈哈哈哈
纪念啊!!!!上榜了居然哈哈哈虽然是抢跑了的…
试了很多次,
1:没理解题意
2:嵌套循环忘了用{}括起来
3.嵌套的两个循环需要用不同的计数变量如i j
4.最后一个循环的最终值弄错了,所以少了一个数!!!

Trees Left

Description:
学校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。
由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。
Input
输入的第一行有两个整数L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域端点的坐标。
Output
输出包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。
Sample Input
500 3
150 300
100 200
470 471Sample Output
298

Hint:
Hint is not available for this exercise.

读题

跟上面的题几乎一样..我就不吐槽了..不过这个有个坑 他给的数据不一定左小右大,所以在scanf之后还要判断交换数据

my answer

#include<stdio.h>
int main() {
    int l, m, i, j, x, y, temp;
    scanf("%d%d", &l, &m);
    int total = l + 1;
    int a[10000] = {};
    for (i = 0; i < m; i++) {
        scanf("%d%d", &x, &y);
        if (x > y) {
            temp = x;
            x = y;
            y = temp;
        }
        for (j = x; j <= y; j++)
            a[j] = 1;
    }
    int dam = 0;
    for (i = 0; i <= total; i++)
    dam += a[i];
    printf("%d\n", total - dam);
    return 0;
}

standard answer

/*
 *from younglee
 */
#include<stdio.h>
#include<string.h>

int main() {
    int m, n, tree[10002], i, res = 0, start, end, temp;
    memset(tree, 1, sizeof(tree));
    scanf("%d%d", &m, &n);

    while (n--) {
        scanf("%d%d", &start, &end);
        if (start > end) {
            temp = start;
            start = end;
            end = temp;
        }
        for (i = start; i <= end; i++) {
            tree[i] = 0;
        }
    }

    for (i = 0; i <= m; i++) {
        if (tree[i]) res++;
    }

    printf("%d\n", res);
    return 0;
}

反馈

跟上面的题几乎一样..我就不吐槽了..不过这个有个坑 他给的数据不一定左小右大,所以在scanf之后还要判断交换数据

熄灯(for hw)

Description:
假设围绕着一个圆形舞台有N个彩灯,编号从0到N-1,1<=N<=50,为了配合演出效果需要进行花式熄灯。熄灯的规则是从第x号灯开始熄灭,然后向编号更大的方向数,每逢y个亮着的灯后灭掉当前数到的亮着的彩灯,直到灭完为止。注意N-1号灯与0号灯互为邻居,数到N-1号灯,下一个为0号灯。
输入:彩灯数量N,第一个灭灯的位置x,以及间隔y,使用空格间隔输入
输出:灭灯的顺序,一行内输出,使用空格间隔,最后一个输出的灯泡编号后面仍然有一个空格,全部输出完毕之后换行
样例:
输入:
10 2 3
输出:
2 5 8 1 6 0 7 4 9 3
Hint:
使用一个长度为N的bool数组保存灯的开关状态

读题

这个题乍一读好像挺简单,结果看了样例之后发现,灭掉的灯不再计数,所以还要判断灯灭了没,再计数

my answer 1

#include<stdio.h>
int main(){
    int n, x, y, i ,k, j = 0;
    scanf("%d%d%d", &n, &x, &y);
    int a[50] = {};
    for (k = 0; k < n; k++){
        printf("%d", x);
        a[x] = 1;
        for (i = 0,j = 0; j != y - 1; i++){
            if (a[x] == 1) {
                x++;
                if (x > n - 1)
                x -= n; 
            } else {
                x++;
                j++;
            if (x > n - 1)
                x -= n;
             }
        }
    }
    return 0; 
}

这个程序我在dev上运行时正确的,然而,系统判超时,我也不知道为何啊

my answer 2

#include<stdio.h>
int main(){
    int n, x, y, i , j; // i为熄灭的灯的数量, j为当前数到的个数 
    scanf("%d%d%d", &n, &x, &y);  //n总灯数,x开始数的灯号,y间隔
    int a[50] = {0};  // a[i]表示i号灯 
    i = 0;
    j = y; 
    while (i < n){
        if (j == y){
            printf("%d ", x);  // 灭掉一个 
            a[x] = 1;  // 灭掉的标记 
            i++;  // 灭掉的数量加一 
            j = 0; // 计数归零 
        } else {
            do {
                x++;
                x %= n;
            } while (a[x] == 1);  // 数下一个灯,当灯标记为灭掉时 重复即再数一个灯 
            j++;  // 数了一个之后,计数加一 
        } 
    }
    printf("\n");
    return 0; 
}

这个是参考了一下别人的做法,修改得来的,暂时还不知道好在哪

standard answer

#include<stdio.h>
#define MAX 100
int main() {
    int lightNumber = 0;
    int gap = 0;
    int counter = 0;
    int offLight = 0;
    int isLight[MAX] = {0};
    int currentPos = 0;
    scanf("%d %d %d", &lightNumber, &currentPos, &gap);
    offLight = lightNumber;
    printf("%d ", currentPos);
    offLight--;
    isLight[currentPos] = 1;
    while (offLight > 0) {
        currentPos = (currentPos + 1) % lightNumber;
        if (isLight[currentPos] == 0)
            counter++;
        if (counter == gap) {
            printf("%d ", currentPos);
            counter = 0;
            isLight[currentPos] = 1;
            offLight--;
        }
    }
    printf("\n");
    return 0;
}

反馈

LEGION

军团再临

燃烧军团即将再次降临艾泽拉斯。萨尔为了改变对抗燃烧军团,使用地震法术,把一处平原改造成了山丘。之后,萨尔需要绘制出新的地图。

平原可以看做一个N*M的棋盘(国际象棋那种)初始海拔为0。每次,萨尔将一个矩阵的海拔全部提高1 。这一个矩阵可以用左上角(sx,sx)和右下角(tx,ty)表示,也即第sx行第sy列的方格到第tx行第ty列的方格这样的一个矩形区域。绘制地图前,萨尔想知道最高的山峰 海拔是多少。使用完地震法术后,萨尔实在太累了,因此他把这个任务交给了你—他最聪明的朋友。
给出平原大小N,M(N行M列,行列都从1开始计算,也即第一行到第N行,第一列到第M列)K 使用地震的次数。N,M,K不超过500
问最高的山峰海拔是多少。
样例输入:
10 10 3
1 1 3 3
3 3 5 5
3 3 10 10
样例输出
3

读题

很明显要用数组,然后因为是一个矩阵,也就是二维的,所以要用二维数组(幸好之前有看到过相关的知识点,不然肯定蒙了

my answer

#include<stdio.h>
int main() {
    int n, m, K, i, j, k, sx, sy, tx, ty;
    scanf("%d%d%d", &n, &m, &K);
    int a[500][500] = {0};
    int max = 0;
    for (i = 0; i < K; i++){
        scanf("%d%d%d%d", &sx, &sy, &tx, &ty);
        for (j = sx; j <= tx; j++){
            for(k = sy; k <= ty; k++)
            a[j][k] += 1; 
        }

    }  // 法术 赋值 
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
        if (a[i][j] > max)
        max = a[i][j];
        }
    }
    printf("%d\n", max);
    return 0;
}

standard answer

#include<stdio.h>
int f[510][510];
int main() {
    int n, m, k, i, j, x, y, ans = 0;
    scanf("%d%d%d", &n, &m, &k);
    for (i = 1; i <= k; i++) {
        int sx, sy, tx, ty;
        scanf("%d%d%d%d", &sx, &sy, &tx, &ty);
        for (x = sx; x <= tx; x++)
            for (y = sy; y <= ty; y++)
                f[x][y]++;
    }
    for (i = 1; i <= n; i++)
        for (j = 1; j <= m; j++) {
            if (ans < f[i][j]) ans = f[i][j];
        }
    printf("%d\n", ans);
    return 0;
}

反馈

只要知道要用二维数组,这道题目没有太大难度,一次过~~~

To and Fro(for hw)

Description
Mo and Larry have devised a way of encrypting messages. They first decide secretly on the number of columns and write the message (letters only) down the columns, padding with extra random letters so as to make a rectangular array of letters. For example, if the message is “There’s no place like home on a snowy night” and there are five columns, Mo would write down t o i o y h p k n n e l e a i r a h s g e c o n h s e m o t n l e w x Note that Mo includes only letters and writes them all in lower case. In this example, Mo used the character `x’ to pad the message out to make a rectangle, although he could have used any letter. Mo then sends the message to Larry by writing the letters in each row, alternating left-to-right and right-to-left. So, the above would be encrypted as toioynnkpheleaigshareconhtomesnlewx Your job is to recover for Larry the original message (along with any extra padding letters) from the encrypted one.
Input
There will be multiple input sets. Input for each set will consist of two lines. The first line will contain an integer in the range 2 . ..20 indicating the number of columns used. The next line is a string of up to 200 lower case letters. The last input set is followed by a line containing a single 0, indicating end of input.
Output
Each input set should generate one line of output, giving the original plaintext message, with no spaces.
Sample Input
Copy sample input to clipboard
5
toioynnkpheleaigshareconhtomesnlewx
3
ttyohhieneesiaabss
0
Sample Output
theresnoplacelikehomeonasnowynightx
thisistheeasyoneab
Hint:
题目来源:http://soj.sysu.edu.cn/show_problem.php?pid=1007

读题

就是给列数和加密后的信息,要打印出原信息.加密方式:将信息按列数竖着排成类似矩阵的东西,不够的用随机字母补充,然后将双数行的字符左右翻转,再横着读取出来的就是加密后的信息.
也就是说,我们需要将得到的信息放到一个数组(一维二维都可以,我个人感觉二维直观点),以二维数组为例,然后将偶数行左右翻转,然后再将矩阵竖着打印出来.
做这个题我修改了好久好久..一开始是没对好号码,解密出错,后来我在dev上面运行,总是出现乱码,运行不成功..所以..我总是以为我哪里做错了..知道后来我绝望的直接把代码提交上去…才发现原来已经是对的了!

my answer

#include <stdio.h>
#include <string.h>
int main() {
    char a[30][200], x[300];
    int n, col, i, j, k;
    for (scanf("%d", &col); col != 0; scanf("%d", &col)) {
        scanf("%s", &x);
        n = strlen(x);
        k = 0;
        for (i = 0; i < n / col; i++) {
            for (j = 0; j < col; j++) {
                if (i % 2)
                a[i][col-j-1] = x[k++];
                else
                a[i][j] = x[k++];  // 将字符排成矩阵,并完成倒置
            }
        }
        for (i = 0; i < col; i++) {
            for (j = 0; j < n/col; j++) {
                printf("%c", a[j][i]);
            }
        }
        printf("\n");
    }
    return 0;
}

standard answer

#include <stdio.h>
#include <string.h>

#define MAXl (200+1)

int main() {
    char s[MAXl];
    unsigned m, n, i, j;
    for (scanf("%u", &n); n > 0; scanf("%u", &n)) {
        scanf("%s", s);
        m = strlen(s) / n;
        for (i = 0; i < n; ++i)
            for (j = 0; j < m; ++j)
                printf("%c", s[j * n + ((j & 1) ? (n - 1 - i) : );
                // 直接在打印的时候倒置,省了一个步骤
        printf("\n");
    }
    return 0;
}

反馈

这个运行出乱码的问题..一个师姐建议直接用IDE,不要用dev否则容易崩..
同时她还教我下载gcc和gdb来调试代码..虽然目前我只是下载了minGW..还没学会怎么用….


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值