洛谷P2404 自然数的拆分 DFS 回溯 去重 字典序

题目

任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。现在给你一个自然数n,要求你求出n的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。
题目地址

题解思路

首先考虑用一个数组记录这一回合的值,并且再用一个step变量记录这个回合数的个数,再开一个sum变量给DFS判断搜索的结束。按照这个思路我写出了部分数字重复相加但有些回合的数字类似进行了排列组合,比如这样:洛谷P2404 自然数的拆分 DFS 回溯 去重 字典序_第1张图片
结果发现再开一个当前采用值的变量放到for循环里面就可以去重,然后还能按字典序排列(一开始搜索时就是从小到大的)

void dfs(int sum,int step,int a)
{
    if(sum>n)
        return ;
    if(sum==n)
    {
        shuchu(step);
        return;
    }
    for(int i=a;i<n;i++)  //这一步关键
    {
        if(sum+i<=n)
        {
            step++;
            daan[step]=i;
            sum+=i;
            dfs(sum,step,i);
            sum-=i;
            step--;
        }
    }
}

然后按照正常DFS就可以AC这题了

AC代码

#include 
#include 
using namespace std;
int n;
int daan[22];
void shuchu (int i)
{
    for(int k=1;k<=i;k++)
    {
        printf("%d",daan[k]);
        if(k!=i)
            printf("+");
    }
    printf("\n");
}
void dfs(int sum,int step,int a)
{
    if(sum>n)
        return ;
    if(sum==n)
    {
        shuchu(step);
        return;
    }
    for(int i=a;i<n;i++)
    {
        if(sum+i<=n)
        {
            step++;
            daan[step]=i;
            sum+=i;
            dfs(sum,step,i);
            sum-=i;
            step--;
        }
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        dfs(0,0,1);
    }
    return 0;
}

你可能感兴趣的:(搜索,dfs,算法)