题解

题目难度:中等难度

知识点:DFS

相关背景知识

递归是一种算法结构,回溯是一种算法思想

递归:

在函数中调用函数本身来解决问题

回溯:

通过不同的尝试来生成问题的解,有点类似于穷举,但是和穷举不同的是回溯会“剪枝”,意思就是对已经知道错误的结果没必要再枚举接下来的答案了,比如一个有序数列1,2,3,4,5,我要找和为5的所有集合,从前往后搜索我选了1,然后2,然后选3 的时候发现和已经大于预期,那么4,5肯定也不行,这就是一种对搜索过程的优化。

回溯搜索是深度优先搜索(DFS)的一种

对于某一个搜索树来说(搜索树是起记录路径和状态判断的作用),回溯和DFS,其主要的区别是,回溯法在求解过程中不保留完整的树结构,而深度优先搜索则记下完整的搜索树。

为了减少存储空间,在深度优先搜索中,用标志的方法记录访问过的状态,这种处理方法使得深度优先搜索法与回溯法没什么区别了。
##方法(一):DFS

本题思路:考虑N=4时

DFS形参有两个sum和p,sum表示在符号为p之前的计算结果。

结束条件:当p==n+1,即所有N个数都用到算式之中,如果sum==M表示该算式符合条件,cnt++。

1.首先考虑两个数之间为“”,从DFS(0,1)考虑便是DFS(1,2)、DFS(12,3)、DFS(123,4)、DFS(1234,5)。

2.当p不等于1时考虑加减法:
如DFS(1,2)考虑加法:DFS(1+2,3)、DFS(1+23,4)、DFS(1+234,5);考虑减法:DFS(1-2,3)、DFS(1-23,4)、DFS(1-234,5);

下图给出了N为4的计算流程:
图片说明

#include<iostream>
using namespace std;
int n,m,cnt=0;
void DFS(int sum, int p){
    if(sum==m && p==n+1)
        cnt++;
    int t = 0;
    for(int i=p;i<=n;i++,t*=10){
        t += i;
        DFS(sum+t, i+1);
        if(p!=1)
            DFS(sum-t,i+1);
    }
}
int main(){
    cin>>n>>m;
    DFS(0,1);
    cout<<cnt<<endl;
    return 0;
}