Files
project1/第01课-数据类型与分支结构/分支结构-编程题-教师版.md

18 KiB
Raw Blame History

第4课编程题教师版

本课知识点覆盖表

核心知识点 GESP等级 对应课堂题
if / else if / else 多层互斥分支 一级必考 课堂1
嵌套 if、逻辑运算与条件分组 一级必考 课堂2
普通打擂台、合法初始擂主 一级/二级 课堂3
二次打擂台、主条件与并列规则 二级 课堂4

本课重点训练多层分支结构。14 题中有 10 题需要三层以上分支或嵌套判断。

一、课堂练习4题

课堂1阶梯电费【适中】

题目描述: 某月用电量不超过 180 度的部分每度 0.50 元181280 度的部分每度 0.60 元;超过 280 度的部分每度 0.80 元。若总电费超过 200 元再加收 5% 服务费。输出应付金额。

输入格式: 输入一个非负整数,表示本月用电量。

输出格式: 应付金额,保留两位小数。

数据范围: 0≤n≤10000

输入样例:

300

输出样例:

166.00

解题思路: 用多层 if-else if-else 分段累计;计算完成后再独立判断是否加收服务费。

参考代码:

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    int n;
    cin >> n;
    double cost;
    if (n <= 180) {
        cost = n * 0.50;
    } else if (n <= 280) {
        cost = 180 * 0.50 + (n - 180) * 0.60;
    } else {
        cost = 180 * 0.50 + 100 * 0.60 + (n - 280) * 0.80;
    }
    if (cost > 200) cost *= 1.05;
    cout << fixed << setprecision(2) << cost;
    return 0;
}

易错提醒: 阶梯收费是分段累计,不是把全部用电量直接乘最高档单价。

课堂2游乐园购票方案【适中】

题目描述: 输入年龄、身高和是否有成人陪同。身高低于 120 厘米免费;否则年龄不满 12 岁时,有成人陪同票价 30 元无陪同不得入园1259 岁票价 80 元60 岁及以上票价 40 元。周末所有非免费票加收 10 元。

输入格式: 依次输入年龄、身高、是否有成人陪同和是否为周末;后两项用 0 或 1 表示。

输出格式: 免费输出 FREE,不得入园输出 DENIED,否则输出票价。

数据范围: 1≤age≤12050≤height≤220

输入样例:

10 135 1 1

输出样例:

40

解题思路: 先判断身高;不免费时再按年龄嵌套判断,儿童分支中继续判断陪同;最后对合法票价判断周末加价。

参考代码:

#include <iostream>
using namespace std;

int main() {
    int age, height, accompanied, weekend;
    cin >> age >> height >> accompanied >> weekend;
    if (height < 120) {
        cout << "FREE";
    } else {
        int price;
        if (age < 12) {
            if (accompanied == 0) {
                cout << "DENIED";
                return 0;
            }
            price = 30;
        } else if (age < 60) {
            price = 80;
        } else {
            price = 40;
        }
        if (weekend == 1) price += 10;
        cout << price;
    }
    return 0;
}

易错提醒: “不得入园”不是票价 0输出后应立即结束避免继续加价。

课堂3最佳选手【适中】

题目描述: 输入 n 名选手的分数,输出最高分和第一次取得该分数的选手编号。

输入格式: 第一行输入选手人数;第二行输入每名选手的分数。

输出格式: 最高分和选手编号(从 1 开始)。

数据范围: 1≤n≤100,分数为 0100

输入样例:

5
88 95 90 95 70

输出样例:

95 2

解题思路: 用第一名选手初始化擂主;只有出现严格更高分时才更新,便可保留最早编号。

参考代码:

#include <iostream>
using namespace std;

int main() {
    int n, score, bestScore, bestId = 1;
    cin >> n >> bestScore;
    for (int id = 2; id <= n; id++) {
        cin >> score;
        if (score > bestScore) {
            bestScore = score;
            bestId = id;
        }
    }
    cout << bestScore << " " << bestId;
    return 0;
}

易错提醒: 擂主必须用第一个合法数据初始化;相等时不更新才能保留第一次出现的位置。

课堂4最接近目标的候选人【适中】

题目描述: 输入目标分 target 以及 n 名候选人的编号和分数。选择与目标分距离最小者;距离相同时选分数较高者;仍相同则选编号较小者。

输入格式: 第一行输入候选人数和目标分;随后每行输入一名候选人的编号和分数。

输出格式: 入选者编号和分数。

数据范围: 1≤n≤100,编号互不相同,分数为 0100

输入样例:

4 80
3 76
8 84
2 84
5 90

输出样例:

2 84

解题思路: 依次比较距离、分数、编号,三层优先级构成完整更新条件。

参考代码:

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    int n, target, id, score, bestId, bestScore;
    cin >> n >> target;
    cin >> bestId >> bestScore;
    for (int i = 1; i < n; i++) {
        cin >> id >> score;
        int d = abs(score - target);
        int bestD = abs(bestScore - target);
        if (d < bestD ||
            (d == bestD && score > bestScore) ||
            (d == bestD && score == bestScore && id < bestId)) {
            bestId = id;
            bestScore = score;
        }
    }
    cout << bestId << " " << bestScore;
    return 0;
}

易错提醒: 三层规则按先后顺序连接,每个次级规则都只能在前级相等时生效。

二、课后作业3题

课后1成绩等级【简单】

题目描述: 输入成绩90100 为 A8089 为 B7079 为 C6069 为 D059 为 E;范围外输出 ERROR

输入格式: 一个整数成绩。

输出格式: 等级或 ERROR

数据范围: 输入整数绝对值不超过 1000。

输入样例:

86

输出样例:

B

解题思路: 先排除非法范围,再从高到低使用多层 else if

参考代码:

#include <iostream>
using namespace std;

int main() {
    int score;
    cin >> score;
    if (score < 0 || score > 100) cout << "ERROR";
    else if (score >= 90) cout << "A";
    else if (score >= 80) cout << "B";
    else if (score >= 70) cout << "C";
    else if (score >= 60) cout << "D";
    else cout << "E";
    return 0;
}

易错提醒: 从高到低判断后,不需要重复写上界。

课后2月份天数【简单】

题目描述: 输入年份和月份,输出该月天数。闰年规则:能被 400 整除,或能被 4 整除但不能被 100 整除。

输入格式: 输入年份和月份。

输出格式: 天数;月份非法输出 ERROR

数据范围: 1≤year≤9999,月份可能为任意整数。

输入样例:

2024 2

输出样例:

29

解题思路: 先验证月份,再判断 2 月2 月内部嵌套判断闰年,其余月份判断 30 天或 31 天。

参考代码:

#include <iostream>
using namespace std;

int main() {
    int year, month;
    cin >> year >> month;
    if (month < 1 || month > 12) {
        cout << "ERROR";
    } else if (month == 2) {
        bool leap = year % 400 == 0 ||
                    (year % 4 == 0 && year % 100 != 0);
        cout << (leap ? 29 : 28);
    } else if (month == 4 || month == 6 ||
               month == 9 || month == 11) {
        cout << 30;
    } else {
        cout << 31;
    }
    return 0;
}

易错提醒: 闰年条件中的括号不能省略概念上的分组。

课后3简单计算器【简单】

题目描述: 输入两个整数和运算符 + - * / %,输出计算结果。除数为 0 时输出 ERROR,未知运算符输出 UNKNOWN

输入格式: 依次输入第一个整数、运算符和第二个整数。

输出格式: 计算结果或错误信息。

数据范围: 两数绝对值不超过 10000。

输入样例:

17 % 5

输出样例:

2

解题思路: 先按运算符多层分支;进入除法或取模分支后再嵌套判断除数。

参考代码:

#include <iostream>
using namespace std;

int main() {
    int a, b;
    char op;
    cin >> a >> op >> b;
    if (op == '+') cout << a + b;
    else if (op == '-') cout << a - b;
    else if (op == '*') cout << a * b;
    else if (op == '/' || op == '%') {
        if (b == 0) cout << "ERROR";
        else if (op == '/') cout << a / b;
        else cout << a % b;
    } else {
        cout << "UNKNOWN";
    }
    return 0;
}

易错提醒: 除法和取模都必须先检查除数是否为 0。

三、扩展练习7题

扩展1体质指数评价【基础综合】

题目描述: 输入体重(千克)和身高(米),计算 BMI。低于 18.5 输出 LOW18.523.9 输出 NORMAL2427.9 输出 HIGH28 及以上输出 VERY HIGH

输入格式: 输入体重和身高两个实数。

输出格式: BMI 等级。

数据范围: 20≤weight≤3001≤height≤2.5

输入样例:

60 1.70

输出样例:

NORMAL

解题思路: 先计算 weight/(height*height),再按从小到大的边界进行多层判断。

参考代码:

#include <iostream>
using namespace std;

int main() {
    double weight, height;
    cin >> weight >> height;
    double bmi = weight / (height * height);
    if (bmi < 18.5) cout << "LOW";
    else if (bmi < 24) cout << "NORMAL";
    else if (bmi < 28) cout << "HIGH";
    else cout << "VERY HIGH";
    return 0;
}

易错提醒: 身高要平方;连续区间判断必须保证没有空档或重叠。

扩展2三角形分类【中等】

题目描述: 输入三条边。不能组成三角形输出 INVALID;否则先按边分类输出 EQUILATERALISOSCELESSCALENE,再输出是否为直角三角形 RIGHTNOT RIGHT

输入格式: 输入三个正整数,表示三条边长。

输出格式: 两行分类结果。

数据范围: 边长不超过 10000。

输入样例:

3 4 5

输出样例:

SCALENE
RIGHT

解题思路: 先判断合法性;合法后分别进行边型判断和直角判断。直角判断需覆盖三条边分别为斜边的情况。

参考代码:

#include <iostream>
using namespace std;

int main() {
    long long a, b, c;
    cin >> a >> b >> c;
    if (a + b <= c || a + c <= b || b + c <= a) {
        cout << "INVALID";
        return 0;
    }
    if (a == b && b == c) cout << "EQUILATERAL\n";
    else if (a == b || a == c || b == c) cout << "ISOSCELES\n";
    else cout << "SCALENE\n";

    if (a * a + b * b == c * c ||
        a * a + c * c == b * b ||
        b * b + c * c == a * a) cout << "RIGHT";
    else cout << "NOT RIGHT";
    return 0;
}

易错提醒: 必须先判断能否组成三角形;平方可能较大,应使用 long long

扩展3快递计费【中等】

题目描述: 基础运费按重量计算:不超过 1 千克 8 元15 千克每增加 1 千克加 3 元,不足 1 千克按 1 千克算;超过 5 千克的部分每千克加 5 元。偏远地区加 10 元,加急再加总价的 20%。

输入格式: 依次输入包裹重量、是否为偏远地区和是否加急;后两项用 0 或 1 表示。

输出格式: 运费,保留两位小数。

数据范围: 0<w≤100

输入样例:

6.2 1 1

输出样例:

48.00

解题思路: 先向上取整重量并按档位计算,再依次处理偏远和加急条件。

参考代码:

#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;

int main() {
    double w;
    int remote, urgent;
    cin >> w >> remote >> urgent;
    int kg = (int)ceil(w);
    double cost;
    if (kg <= 1) cost = 8;
    else if (kg <= 5) cost = 8 + (kg - 1) * 3;
    else cost = 8 + 4 * 3 + (kg - 5) * 5;
    if (remote) cost += 10;
    if (urgent) cost *= 1.2;
    cout << fixed << setprecision(2) << cost;
    return 0;
}

易错提醒: 示例中 6.2 千克按 7 千克计算;加急费在偏远附加费之后计算。

扩展4石头剪刀布裁判【中等】

题目描述: 输入两名选手的手势 R(石头)、S(剪刀)、P(布)。非法手势输出 ERROR;相同输出 DRAW;否则输出 AB

输入格式: 两个字符。

输出格式: 裁判结果。

数据范围: 任意可见字符。

输入样例:

R S

输出样例:

A

解题思路: 先检查两个手势是否合法;再判断平局;最后用三个获胜组合判断 A 是否获胜。

参考代码:

#include <iostream>
using namespace std;

int main() {
    char a, b;
    cin >> a >> b;
    bool validA = a == 'R' || a == 'S' || a == 'P';
    bool validB = b == 'R' || b == 'S' || b == 'P';
    if (!validA || !validB) cout << "ERROR";
    else if (a == b) cout << "DRAW";
    else if ((a == 'R' && b == 'S') ||
             (a == 'S' && b == 'P') ||
             (a == 'P' && b == 'R')) cout << "A";
    else cout << "B";
    return 0;
}

易错提醒: 合法性判断必须放在胜负判断之前。

扩展5奖学金评定【中等】

题目描述: 输入平均分、竞赛获奖次数、志愿服务时长和是否违纪。违纪直接输出 NONE否则平均分≥90 且获奖≥2 为一等奖平均分≥85 且获奖≥1 或服务≥50为二等奖平均分≥80 或服务≥100 为三等奖,其余无奖。

输入格式: 依次输入平均分、获奖次数、志愿服务时长和是否违纪。

输出格式: FIRSTSECONDTHIRDNONE

数据范围: 平均分 0100,其余为非负整数,违纪用 0/1 表示。

输入样例:

87 0 60 0

输出样例:

SECOND

解题思路: 违纪是最高优先级;未违纪时按奖项从高到低判断,括号明确“且”“或”的组合。

参考代码:

#include <iostream>
using namespace std;

int main() {
    int average, awards, service, violation;
    cin >> average >> awards >> service >> violation;
    if (violation) cout << "NONE";
    else if (average >= 90 && awards >= 2) cout << "FIRST";
    else if (average >= 85 && (awards >= 1 || service >= 50))
        cout << "SECOND";
    else if (average >= 80 || service >= 100) cout << "THIRD";
    else cout << "NONE";
    return 0;
}

易错提醒: 一定要从高等级奖项向低等级判断,否则较宽条件会抢先匹配。

扩展6最佳商品【略难】

题目描述: 输入 n 件商品的编号、价格和评分。选择评分最高的商品;评分相同时价格更低者优先;仍相同则编号更小者优先。

输入格式: 第一行输入商品数量;随后每行输入一件商品的编号、价格和评分。

输出格式: 最佳商品编号。

数据范围: 1≤n≤100,价格和评分为正整数。

输入样例:

4
5 100 9
2 120 9
8 80 8
3 100 9

输出样例:

3

解题思路: 第一优先级比较评分,第二优先级比较价格,第三优先级比较编号。

参考代码:

#include <iostream>
using namespace std;

int main() {
    int n, id, price, score;
    int bestId, bestPrice, bestScore;
    cin >> n >> bestId >> bestPrice >> bestScore;
    for (int i = 1; i < n; i++) {
        cin >> id >> price >> score;
        if (score > bestScore ||
            (score == bestScore && price < bestPrice) ||
            (score == bestScore && price == bestPrice && id < bestId)) {
            bestId = id;
            bestPrice = price;
            bestScore = score;
        }
    }
    cout << bestId;
    return 0;
}

易错提醒: 不要用任意极值初始化三个擂台变量,直接读入第一件商品最安全。

扩展7综合录取规则【略难】

题目描述: 输入笔试、面试、体育三项成绩,以及是否有竞赛一等奖。任一成绩不在 0100 输出 ERROR。竞赛一等奖且笔试≥70 可直接录取否则笔试≥85 时面试≥80 且体育≥60 录取;笔试 7584 时面试≥90 且体育≥70 才录取;其他情况不录取。

输入格式: 依次输入笔试成绩、面试成绩、体育成绩和是否获得竞赛一等奖;最后一项用 0 或 1 表示。

输出格式: ADMITTEDREJECTEDERROR

数据范围: 成绩可能为任意整数。

输入样例:

78 92 75 0

输出样例:

ADMITTED

解题思路: 先做数据合法性检查,再判断特殊录取,最后按笔试档位嵌套判断面试和体育条件。

参考代码:

#include <iostream>
using namespace std;

int main() {
    int written, interview, sport, prize;
    cin >> written >> interview >> sport >> prize;
    if (written < 0 || written > 100 ||
        interview < 0 || interview > 100 ||
        sport < 0 || sport > 100) {
        cout << "ERROR";
    } else if (prize == 1 && written >= 70) {
        cout << "ADMITTED";
    } else if (written >= 85) {
        if (interview >= 80 && sport >= 60) cout << "ADMITTED";
        else cout << "REJECTED";
    } else if (written >= 75) {
        if (interview >= 90 && sport >= 70) cout << "ADMITTED";
        else cout << "REJECTED";
    } else {
        cout << "REJECTED";
    }
    return 0;
}

易错提醒: 数据检查、特殊规则、普通规则的优先级不能调换。