题解:洛谷 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

【核心思想】

  1. 问题分析:有 10 种配料,每种配料的用量只能是 1、2 或 3 克。给定总美味程度 \(n\)(即所有配料质量之和),需要找出所有可能的配料用量组合,按字典序输出方案总数和具体方案。由于每种配料只有 3 种选择,总共 \(3^{10} = 59049\) 种组合,完全枚举是可行的。

  2. 算法选择

    • 十重循环枚举:直接使用 10 层嵌套循环遍历所有可能的用量组合(每层循环 1 到 3),检查总和是否等于 \(n\)。如果相等,则记录方案并输出。
    • DFS 搜索(备选):也可用深度优先搜索生成所有组合,但嵌套循环在此题中足够简洁。
    • 复杂度\(3^{10} = 59049\) 种组合,每次检查 \(O(1)\),总操作约 6 万次,非常快。
  3. 关键步骤

    • 读入:读取 \(n\)
    • 合法性检查:若 \(n < 10\)\(n > 30\),则无解(因为每种配料至少 1 克,最多 3 克),输出 0 并结束。
    • 第一次遍历:统计满足条件的方案总数。
    • 第二次遍历:再次遍历所有组合,输出满足条件的方案(按字典序,因为循环顺序天然是从小到大)。
    • 输出:先输出方案总数,再输出每个方案。
  4. 时间/空间复杂度

    • 时间复杂度:\(O(3^{10})\)
    • 空间复杂度:\(O(1)\)
  5. 暴力枚举

    • 数据规模小\(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
posted @ 2026-08-31 09:26  团爸讲算法  阅读(16)  评论(0)    收藏  举报