题面(from luogu)
自然数的拆分
任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。
输入格式:
输入:待拆分的自然数n。
输出格式:
输出:若干数的加法式子。
样例.in
7
样例.out
1+1+1+1+1+1+1
1+1+1+1+1+2
1+1+1+1+3
1+1+1+2+2
1+1+1+4
1+1+2+3
1+1+5
1+2+2+2
1+2+4
1+3+3
1+6
2+2+3
2+5
3+4
题目分析
这是一道很典型的DFS题,针对题目,我们可以设较多的形参,以便使用,同时,也要注意重复的情况
大体框架
void search(int k,int total,int now); //k表示找到那一个位置了,total是目前累和的情况,now是当前拆分到的数
{
if (total == n) 输出 //total==n,即是拆出的数相加同原数大小,输出
else //反之,继续找
for (......)
{
if ())
{
记录下来;
向前一步搜索;
}
}
代码
#include <bits/stdc++.h>
using namespace std;
int a[50],n; //a是答案数组
void write(int c) //输出
{
for (int i = 1; i < c; i++)
cout<<a[i]<<'+';
cout<<a[c]<<endl; //注意,最后一个要单独输出,不然会多一个0
// cout<<c<<endl;
}
void search(int k,int total,int now) //k表示找到那一个位置了,total是目前累和的情况,now是当前拆分到的数
{
if (total == n) write(k-1); //如果找到了,total==n,即是拆出的数相加同原数大小,输出
else //反之,继续找
{
for (int i = 1; i < n; i++) //注意,是小于n的,这样可以避免输出n的情况
if (total + i <= n && i >= now) //加上的和不超过n && i与当前的now相等或更大
{
a[k]=i; //记录答案
search(k+1,total+i,i); //输入新的实参
// total-=i;
}
}
}
int main()
{
cin>>n; //输入
search(1,0,1); //开始搜索
/*到了这里,大家可能会有一定的疑问,这样为啥不会重复呢,对此,我来解释一下:
因为在程序中的这个部分:if (total + i <= n && i >= now) ......就确定了,在后面的的数,都>=前一个,由此便不会重复了 */
}
**蒟蒻新星c_uizrp_dzjopkl原创**