洛谷P1192台阶问题(单向递归dfs,逆向递归记忆化)

题目链接:https://www.luogu.org/problemnew/show/P1192

题目很有价值,用搜索写的话,可以加深对递归搜索的理解。一般这样的递推可以用:dp或记忆化(我就用记忆化了

记忆化一般有递推规律(递归好写就在这),适用于递推题!数范围略大题!一般逆向递归dfs到头递归出口结束!(代表阶乘,斐波那契数列,台阶问题):就找前一个解,递归下去直到递归出口返回,再记录下来。

没有递推规律,找出所有情况方法(递归难写就在这),适用于暴力题!数范围小题!一般正向递归dfs到尾递归出口结束!(代表数的划分,全排列,八皇后)

刚开始,直接正向递归dfs,最暴力的原始走,把所有方法都试一遍,走到头位置,过了一个点超时四个。。

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 #include <iomanip>
 5 #include <cstdio>
 6 #include <cstring>
 7 #include <cmath>
 8 using namespace std;
 9 typedef long long ll;
10 typedef unsigned long long ull;
11 const int maxn=1e6+5;
12 const int mod=100003;
13 int a[maxn];
14 int n,k;
15 int ans;
16 
17 void so(int sum,int step)
18 {
19     if(sum==n)
20     {
21         ans++;
22         //for(int i=0;i<=step-1;i++) cout<<a[i]<<' ';//排列输出,方便观察是否正确
23         //cout<<endl;
24         return;
25     }
26 
27     for(int i=1;i<=k;i++)
28     {
29         if(sum+i>n) break;
30         //a[step]=i;//排列输出,方便观察是否正确
31         so(sum+i,step+1);
32     }
33 }
34 
35 
36 int main()
37 {
38     ios::sync_with_stdio(false); cin.tie(0);
39 
40     while(cin>>n>>k)
41     {
42         ans=0;
43         so(0,0);
44 
45         cout<<ans<<endl;
46     }
47 
48     //if(n==1 || k==1) cout<<'1'<<endl;
49     //if(k>n) k=n;
50 
51     return 0;
52 }

之后又想能不能记忆化保存起来,但好像没办法啊,看了大佬题解后,果然是我太菜。。。

可以逆向递归dfs然后保存起来啊,逆向递归,这样就有规律了,很容易保存记忆化。(一般正向不行就试试逆向会有惊喜!)

猜你喜欢

转载自www.cnblogs.com/redblackk/p/9815262.html