用 DFS 按非递减顺序拆分 n,自然去重并按字典序输出所有方案。
OJ: roj
题目 ID: 1318
难度:入门
标签:DFS搜索整数拆分
创建: 2026-09-30 04:53
更新: 2026-10-05 09:19
题目描述
输入一个大于 1 的自然数
思路
DFS 枚举时限制下一个加数不小于上一个加数,这样每种无序拆分只出现一次,且从小到大枚举天然满足字典序。剩余值为 0 时输出当前方案。
参考代码
Python 版:
python
#!/usr/bin/env python3
# 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-05 21:47
# update_at: 2026-07-05 21:47
import sys
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
n = next(data, None)
if n is None: # 空输入防御:没有位置量就直接结束
return
out: list[str] = []
def dfs(rest: int, start: int, path: list[int]) -> None:
"""按非递减顺序搜索 rest 的拆分,path 记录已选加数。"""
if rest == 0:
out.append(f"{n}={'+'.join(map(str, path))}")
return
# 下一个加数不小于上一个(保证不重复),且必须小于 n
for x in range(start, rest + 1):
if x < n:
path.append(x)
dfs(rest - x, x, path)
path.pop()
dfs(n, 1, [])
sys.stdout.write('\n'.join(out))
if __name__ == "__main__":
solve()C++ 版(同一算法):
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-10-05 09:17
* update_at: 2026-10-05 09:17
*/
#include <cstdio>
typedef long long ll;
const int MAXN = 1000; // 拆分路径长度上界
ll n; // 待拆分的自然数
ll path[MAXN]; // 当前拆分方案
// 按非递减顺序搜索 rest 的拆分,start 为下一个加数的最小允许值,len 为已选加数个数
void dfs(ll rest, ll start, int len) {
if (rest == 0) {
printf("%lld=%lld", n, path[0]);
for (int i = 1; i < len; ++i) {
printf("+%lld", path[i]);
}
putchar('\n');
return;
}
for (ll x = start; x <= rest; ++x) {
if (x < n) { // 每个加数必须小于 n
path[len] = x;
dfs(rest - x, x, len + 1);
}
}
}
int main() {
scanf("%lld", &n);
dfs(n, 1, 0);
return 0;
}