题解
题目难度:中等难度
知识点: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; }