题目链接: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然后保存起来啊,逆向递归,这样就有规律了,很容易保存记忆化。(一般正向不行就试试逆向会有惊喜!)