用 itertools.product 枚举 10 种配料各取 1 到 3 的所有状态,筛出总和等于 n 的方案。
OJ: luogu
题目 ID: P2089
难度:入门
标签:枚举DFSpython
日期: 2026-07-15 21:30
题意
有 10 种配料,每种配料可以放 1,2,3 克。给定总美味程度 n,输出所有总和等于 n 的方案,按字典序排列。
思路
每个位置都有 1,2,3 三种选择,一共是:
text
3^10 = 59049种方案,可以直接枚举。
Python 的 itertools.product(range(1, 4), repeat=10) 正好表示“10 个位置,每个位置从 1 到 3 中选一个”。product 产生的顺序就是字典序,因此筛选后直接输出即可。
Python 知识
product(range(1, 4), repeat=10)可以代替 10 层循环。sum(plan)直接计算一个方案的总质量。print(*plan)把元组拆开,用空格分隔输出。- 这里需要先保存全部合法方案,因为第一行要输出方案总数。
参考笔记:
/home/rainboy/mycode/hugo-blog/content/program_language/python/brute_force_validation.md/home/rainboy/mycode/hugo-blog/content/program_language/python/itertools_recipes.md/home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md
代码
python
from itertools import product
n = int(input())
plans = [
plan
for plan in product(range(1, 4), repeat=10)
if sum(plan) == n
]
print(len(plans))
for plan in plans:
print(*plan)cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-27 00:00
* update_at: 2026-07-27 00:00
*/
#include <bits/stdc++.h>
using namespace std;
int n, cnt;
int choose[11]; // choose[1..10] 每种配料的选择
int ans[60000][11]; // 保存所有方案,最多 3^10=59049
void dfs(int dep) {
if (dep == 11) {
int sum = 0;
for (int i = 1; i <= 10; i++) sum += choose[i];
if (sum == n) {
cnt++;
for (int i = 1; i <= 10; i++) ans[cnt][i] = choose[i];
}
return;
}
for (int i = 1; i <= 3; i++) {
choose[dep] = i;
dfs(dep + 1);
}
}
int main() {
cin >> n;
dfs(1);
cout << cnt << endl;
for (int i = 1; i <= cnt; i++) {
for (int j = 1; j <= 10; j++) {
cout << ans[i][j];
if (j < 10) cout << " ";
}
cout << endl;
}
return 0;
}复杂度
总共枚举
总结
当每个位置都有固定候选值时,product 是非常适合 Python 初学者模仿的枚举工具。