题解:洛谷 P2089 烤鸡
【题目来源】
洛谷:P2089 烤鸡 - 洛谷(luogu.com.cn)
【题目描述】
猪猪 Hanke 特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke 吃鸡很特别,为什么特别呢?因为他有 \(10\) 种配料(芥末、孜然等),每种配料可以放 \(1\) 到 \(3\) 克,任意烤鸡的美味程度为所有配料质量之和。
现在,Hanke 想要知道,如果给你一个美味程度 \(n\) ,请输出这 \(10\) 种配料的所有搭配方案。
【输入】
一个正整数 \(n\),表示美味程度。
【输出】
第一行,方案总数。
第二行至结束,\(10\) 个数,表示每种配料所放的质量,按字典序排列。
如果没有符合要求的方法,就只要在第一行输出一个 \(0\)。
【输入样例】
11
【输出样例】
10
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 1
1 1 1 1 1 1 1 2 1 1
1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1
1 1 2 1 1 1 1 1 1 1
1 2 1 1 1 1 1 1 1 1
2 1 1 1 1 1 1 1 1 1
【核心思想】
-
问题分析:有 10 种配料,每种配料的用量只能是 1、2 或 3 克。给定总美味程度 \(n\)(即所有配料质量之和),需要找出所有可能的配料用量组合,按字典序输出方案总数和具体方案。由于每种配料只有 3 种选择,总共 \(3^{10} = 59049\) 种组合,完全枚举是可行的。
-
算法选择:
- 十重循环枚举:直接使用 10 层嵌套循环遍历所有可能的用量组合(每层循环 1 到 3),检查总和是否等于 \(n\)。如果相等,则记录方案并输出。
- DFS 搜索(备选):也可用深度优先搜索生成所有组合,但嵌套循环在此题中足够简洁。
- 复杂度:\(3^{10} = 59049\) 种组合,每次检查 \(O(1)\),总操作约 6 万次,非常快。
-
关键步骤:
- 读入:读取 \(n\)。
- 合法性检查:若 \(n < 10\) 或 \(n > 30\),则无解(因为每种配料至少 1 克,最多 3 克),输出
0并结束。 - 第一次遍历:统计满足条件的方案总数。
- 第二次遍历:再次遍历所有组合,输出满足条件的方案(按字典序,因为循环顺序天然是从小到大)。
- 输出:先输出方案总数,再输出每个方案。
-
时间/空间复杂度:
- 时间复杂度:\(O(3^{10})\)。
- 空间复杂度:\(O(1)\)。
-
暴力枚举:
- 数据规模小:\(3^{10}\) 是可控的,因此直接枚举所有组合是最简单直接的方法。
- 字典序输出:由于循环顺序是按 a0 到 a9 递增,天然满足字典序。
- 适用场景:当状态空间有限且可穷举时,暴力枚举是最可靠的解法。
【解题思路】

【算法标签】
普及- #模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, ans=0;
cin >> n; // 输入目标和n
// 检查n的范围是否合法(10到30)
if (n<10 || n>30) {
cout << 0; // 不合法直接输出0
return 0;
}
// 十层嵌套循环,每层代表一个数字(a0到a9),每个数字取值1-3
for (a0=1; a0<=3; a0++) {
for (a1=1; a1<=3; a1++) {
for (a2=1; a2<=3; a2++) {
for (a3=1; a3<=3; a3++) {
for (a4=1; a4<=3; a4++) {
for (a5=1; a5<=3; a5++) {
for (a6=1; a6<=3; a6++) {
for (a7=1; a7<=3; a7++) {
for (a8=1; a8<=3; a8++) {
for (a9=1; a9<=3; a9++) {
// 检查当前组合的和是否等于n
if (a0+a1+a2+a3+a4+a5+a6+a7+a8+a9==n) {
ans++; // 计数器增加
}
}
}
}
}
}
}
}
}
}
}
// 输出满足条件的组合数量
cout << ans << endl;
// 再次遍历所有可能组合,输出每个有效组合
for (a0=1; a0<=3; a0++) {
for (a1=1; a1<=3; a1++) {
for (a2=1; a2<=3; a2++) {
for (a3=1; a3<=3; a3++) {
for (a4=1; a4<=3; a4++) {
for (a5=1; a5<=3; a5++) {
for (a6=1; a6<=3; a6++) {
for (a7=1; a7<=3; a7++) {
for (a8=1; a8<=3; a8++) {
for (a9=1; a9<=3; a9++) {
// 检查并输出满足条件的组合
if (a0+a1+a2+a3+a4+a5+a6+a7+a8+a9==n) {
printf("%d %d %d %d %d %d %d %d %d %d\n",
a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
}
}
}
}
}
}
}
}
}
}
return 0;
}
【运行结果】
11
10
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 1
1 1 1 1 1 1 1 2 1 1
1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1
1 1 2 1 1 1 1 1 1 1
1 2 1 1 1 1 1 1 1 1
2 1 1 1 1 1 1 1 1 1
浙公网安备 33010602011771号