洛谷P2404 自然数的拆分 2019.7.25
题目描述
任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。现在给你一个自然数n,要求你求出n的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。
输入格式
输入:待拆分的自然数n。
输出格式
输出:若干数的加法式子,方案总数。
输入输出样例
输入 #1 复制
7
输出 #1 复制
7=1+1+1+1+1+1+1
7=1+1+1+1+1+2
7=1+1+1+1+3
7=1+1+1+2+2
7=1+1+1+4
7=1+1+2+3
7=1+1+5
7=1+2+2+2
7=1+2+4
7=1+3+3
7=1+6
7=2+2+3
7=2+5
7=3+4
total=14
审题:
1.按字典序排列,后面添加的数始终大于等于前一个数字。
2.sum=n
算法及思路:
1.既然可以从小找到大,考虑用深,遍历所有小于n的数+记忆化搜索来做
2.dfs函数的设置,考虑当前状态:
比如待拆分的数字为num,可以考虑减去从i到num-1的所有数,这个地方可以考虑用循环来找减数,同时注意到减数受到来自前一步的减数的限制,这一步的数必须大于等于前一步的数,设该减数为t。那么此时num=num-t,问题转化为拆分num-t,可以用递归实现。
3.从上方的描述中可以看出,dfs函数需要维护至少两个参数:当前正在拆分的数以及当前拆分的次数。前者容易明白,后者呢??因为受到来自前一个减数的限制,可以考虑用一个数组a来记录每一步的减数,那么要求i>=a[step-1]即可!!!同时,由于记录了每一步的减数,那么最后当num==0时打印拆分数序列的问题也就迎刃而解了(只需要遍历从a数组1到step的所有元素即可)。同时,保留了前一种拆分方法的主体,当dfs函数返回上层栈时,只需要更改最后的几个数就行了,不必重新遍历前方的选择值。
元素解释:
dfs(int num,i