自然数的拆分(DFS)

题面(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原创**

猜你喜欢

转载自blog.csdn.net/c_uizrp_dzjopkl/article/details/81748302