「几种走法?几套搭配?」——数「有多少种」有两把金钥匙:二选一把数相加,一步一步把数相乘。
想象你要从学校(A)到同学家(B)。可以坐火车(3 种车次),也可以坐大巴(2 种线路)。只要挑其中一类就能完成「A→B」,所以总走法 = 3 + 2 = 5 种——这叫加法原理,关键是「二选一,任何一类单独就能办成事」。
再想一件出门的事:先挑上衣(3 件),再挑裤子(4 条),两步都做完才算穿好。两步缺一不可,所以总搭配 = 3 × 4 = 12 套——这叫乘法原理,关键是「一步一步,每一步都要做」。
一句话口诀:「分类能单独办成 → 加;分步才办得成 → 乘」。
从 A 到 B:火车 3 种车次、大巴 2 种线路。注意——只坐火车就能到,只坐大巴也能到:每一类单独拿出来都能完成「A→B」这件事,这叫「二选一」。所以把各类的走法加起来。
// 手推:加法原理(二选一 → 相加) A → B:火车 3 种 + 大巴 2 种 = 5 种 // 类别更多也一样:火车 3、大巴 2、直飞航班 4 3 + 2 + 4 = 9 种 // 「分类不重不漏」两条铁律: // ① 不重:同一种走法只能算进一个类别(不能重复计数) // ② 不漏:每种走法都必须被某个类别覆盖(不能漏数) // 反例(重了):把「坐火车 3 种」和「坐陆路车辆 5 种」当两个类别相加, // 火车的 3 种被数了两次 → 3 + 5 = 8 是错的,正确还是 5 种。
3 件上衣(A、B、C)、4 条裤子(1、2、3、4)。穿好需要两步:先选上衣、再选裤子——只穿上衣不算穿好,只穿裤子也不算。每一步都办不成整件事,所以把各步的选择数乘起来。动手枚举一遍,数一数:
// 手推:枚举所有搭配(固定上衣,逐条配裤子) A-1 A-2 A-3 A-4 // 上衣 A 能配 4 种 B-1 B-2 B-3 B-4 // 上衣 B 能配 4 种 C-1 C-2 C-3 C-4 // 上衣 C 能配 4 种 // 数一数:4 + 4 + 4 = 12 套 // 换个角度:每一件上衣都能配 4 条裤子,3 件上衣 → 3 × 4 = 12 套 // 三步也行:凉菜 3 种、热菜 4 种、饮料 2 种,各选 1 份 = 1 份套餐 3 × 4 × 2 = 24 份(先选凉菜,再选热菜,再选饮料,三步相乘)
// 判断流程(背下来): // 要做「一件事」,问:单独一类能办成整件事吗? // ├─ 能(二选一)→ 加法原理,各类相加 // └─ 不能,要一步步做(分步)→ 乘法原理,各步相乘 // 题 1(加):午餐只点 1 道菜,凉菜 3 种或热菜 4 种 → 3 + 4 = 7 种 // 分析:只点一道,点凉菜或点热菜都办成「点菜」→ 二选一 → 加 // 题 2(乘):套餐 = 1 凉菜 + 1 热菜 → 3 × 4 = 12 种 // 分析:两道都要有,缺一道就不算套餐 → 分步 → 乘 // 题 3(混合:先加后乘):点 1 道菜(凉菜或热菜)+ 1 杯饮料(2 种) // 第一步「选菜」内部是二选一:3 + 4 = 7 种 // 「选菜」和「选饮料」是两步:7 × 2 = 14 种 // 题 4(进阶):甲乙丙丁 4 人,选 3 人分别当班长、副班长、宣传委员,多少种? // 第一步当班长:4 人选 1 → 4 种 // 第二步当副班长:剩下 3 人选 1 → 3 种(班长不能再当) // 第三步当宣传委员:剩下 2 人选 1 → 2 种 // → 4 × 3 × 2 = 24 种(每步的选择数取决于前面的结果)
把两条原理写进代码:套餐 = 凉菜 + 热菜 + 饮料三步 → 相乘;单点 = 只点 1 道菜(凉菜或热菜)→ 相加。再用三重循环把套餐一一列出来(只列前 5 种,防止刷屏)。
// 输入:凉菜数 a、热菜数 b、饮料数 c // 输出:套餐总数(乘法)、单点总数(加法)、前 5 种套餐 #include <iostream> using namespace std; int main() { int a, b, c; cin >> a >> b >> c; cout << "套餐总数: " << a * b * c << endl; // 三步 → 相乘 cout << "单点总数: " << a + b << endl; // 只点 1 道菜 → 相加 int cnt = 0; // 已列出的套餐数 for (int i = 1; i <= a && cnt < 5; i++) // 凉菜 1..a for (int j = 1; j <= b && cnt < 5; j++) // 热菜 1..b for (int k = 1; k <= c && cnt < 5; k++, cnt++) cout << "套餐" << cnt + 1 << ": 凉" << i << " 热" << j << " 饮" << k << endl; return 0; } // 示例:输入 3 4 2 → 套餐总数: 24 / 单点总数: 7 / 列出套餐 1~5 // 输入 1 1 1 → 套餐总数: 1 / 单点总数: 2 / 套餐1: 凉1 热1 饮1
cnt < 5 是干什么用的?去掉后会发生什么?③ 想只枚举「凉菜 + 热菜」(不配饮料)的搭配,循环要改哪里?a + b + c(那是「只点 1 份」的单点逻辑),或把单点总数写成 a * b(那是套餐逻辑)。写代码前先问一句:办成这件事要几步?一步就能办成就加,要多步就乘。// 输入:凉菜数 a、热菜数 b、饮料数 c // 输出:① 套餐总数(三步 → 乘)② 单点总数(一道菜 → 加) // ③ 套餐数不多时全枚举 ④ 新增 1 种凉菜后多几份套餐 // 示例:输入 3 4 2 → 套餐 24 / 单点 7 / 列出 24 份 / 新增凉菜多 8 份 #include <iostream> using namespace std; int main() { int a, b, c; cin >> a >> b >> c; cout << "套餐总数: " << a * b * c << endl; // 凉+热+饮 三步 → 乘 cout << "单点总数: " << a + b << endl; // 凉菜或热菜 → 加 // 套餐数量不大时(≤30),把每份套餐都列出来 if (a * b * c <= 30) { int cnt = 0; for (int i = 1; i <= a; i++) for (int j = 1; j <= b; j++) for (int k = 1; k <= c; k++) { cnt++; cout << "套餐" << cnt << ": 凉" << i << " 热" << j << " 饮" << k << endl; } } // 新增 1 种凉菜:新总数 (a+1)*b*c,比原来多 b*c 份 // (每种「热+饮」组合都多配一份新凉菜 → b*c 份) cout << "新增 1 种凉菜: 多 " << b * c << " 份套餐" << endl; return 0; } // 动手验证:输入 1 1 1 → 套餐 1 / 单点 2 / 套餐1: 凉1 热1 饮1 / 多 1 份