淺談數位DP的dfs寫法
阿新 • • 發佈:2018-11-08
跟著洛穀日報走,演算法習題全都有!
嗯,沒錯,這次我也是看了洛穀日報的第84期才學會這種演算法的,也感謝Mathison大佬,素不相識,卻寫了一長篇文章來幫助我學習這個演算法。
演算法思路:
感覺dfs版的數位dp還是挺簡單的,直接dp然後遞推統計答案的那種比它搞腦子多了。
在dfs版本中,我們需要特別注意的地方有兩個:
1、是否貼上界:
這是個啥呢?
很簡單,給大家舉個栗子,假如我們要求解1-12345這段區間,如果我們已經做了3位,而前三位正好是123,那麼我們第4位就只能取0-5,否則我們就可以取0-9。
2、有沒有前導零:
這有為啥要特殊記呢?
因為前導零會影響我們對合法方案的統計。
當現在的狀態有前導零,或者貼上界的時候我們就不能記憶化,因為它們是與別的狀態不同的,不同之處就是上面講的那些啦。
dfs模板:
function dfs(pos,...,lead,flag:Longint):int64; var res:int64; i,limit:Longint; begin
//pos:當前在做第幾位。
//lead:0/1 有/沒有 前導零
//flag:0/1 是/否 貼上界 if pos>len then exit(...); ...... ...... //各種優化if (dp[pos][...]<>-1)and(lead+flag=0) then exit(dp[pos][...]); //記憶化 if flag=1 then limit:=a[len-pos+1] else limit:=9; //最高列舉到幾 res:=0; for i:=0 to limit do res:=res+dfs(pos+1,...,...,ord((lead=1)and(i=0)),ord((flag=1)and(i=limit))); if lead+flag=0then dp[pos][...]:=res; dfs:=res; end; function part(x:int64):int64; //數位分離 begin len:=0; part:=0;while x>0 do begin inc(len); a[len]:=x mod 10; x:=x div 10; end;
part:=dfs(1,...,1,1);end;