1. 程式人生 > >洛谷P1192臺階問題(單向遞迴dfs,逆向遞迴記憶化)

洛谷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然後儲存起來啊,逆向遞迴,這樣就有規律了,很容易儲存記憶化。(一般正向不行就試試逆向會有驚喜!)