模板 動態規劃 數字dp

2022-05-07 23:09:32 字數 2120 閱讀 6504

#includeusing

namespace

std;

#define ll long long

int a[20

];ll dp[

20][20

/*可能需要的狀態1

*/][20

/*可能需要的狀態2

*/];//

不同題目狀態不同

ll dfs(int pos,int state1/*

可能需要的狀態1

*/,int state2/*

可能需要的狀態2

*/,bool lead/*

這一位的前面是否為零

*/,bool limit/*

這一位是否取值被限制(也就是上一位沒有解除限制)*/)

//不是每個題都要處理前導零

//計算完,記錄狀態

if(!limit && !lead)

dp[pos][state1][state2]=ans;

/*這裡對應上面的記憶化,在一定條件下時記錄,保證一致性,當然如果約束條件不需要考慮lead,這裡就是lead就完全不用考慮了

*/return

ans;

}ll solve(ll x)

return dfs(pos-1

/*從最高位開始列舉

*/,0

/*可能需要的狀態1

*/,0

/*可能需要的狀態2

*/,true,true);//

剛開始最高位都是有限制並且有前導零的,顯然比最高位還要高的一位視為0嘛

}int

main()

}

其實另一種計數寫法對別的題目有一定的啟發性,需要特別注意的是,無論哪種寫法的dp結果中存的數字都是和le與ri無關的。所以在數字受限時不能取用計算過的dp值,也不能更新dp值,不受限的情況可以重複利用。

#includeusing

namespace

std;

#define ll long long

int a[20

];ll dp[

20][maxs1][maxs2];

ll dfs(

int pos,int s1,int s2,bool lead,bool

limit)

if(!limit && !lead && dp[pos][s1][s2]!=-1

)

return

dp[pos][s1][s2];

int up=limit?a[pos]:9

; ll ans=0

;

for(int i=0; i<=up; i++)

if(!limit && !lead)

dp[pos][s1][s2]=ans;

return

ans;

}ll solve(ll x)

return dfs(pos-1,inits1,inits2,true,true);}

intmain()

}

乙個更簡單的模板,去掉了很多奇奇怪怪的東西,比如前導0,前導0的確應該特殊考慮而不能一概而論。

int dfs(int i, int s, bool

e)

看起來清爽多了,其中:

f為記憶化陣列;

i為當前處理串的第i位(權重表示法,也即後面剩下i+1位待填數);

s為之前數字的狀態(如果要求後面的數滿足什麼狀態,也可以再記乙個目標狀態t之類,for的時候列舉下t);

e表示之前的數是否是上界的字首(即後面的數能否任意填)。

for迴圈列舉數字時,要注意是否能列舉0,以及0對於狀態的影響,有的題目前導0和中間的0是等價的,但有的不是,對於後者可以在dfs時再加乙個狀態變數z,表示前面是否全部是前導0,也可以看是否是首位,然後外面統計時候列舉一下位數。

注意:

不滿足區間減法性質的話,不能用solve(r)-solve(l-1)。

看了學長的部分部落格之後發現其實使用f[i][j][st]表示以j開頭的i位數滿足條件st的數的個數也是可以的。待更新。

動態規劃之數字dp

數字dp,字面意思理解就是在數字的每一位上面去dp,動態規劃一般有兩種 遞推,記憶化搜尋 dfs 這裡就是用的記憶化。一般這種用在計數上面,對那些數字上面有限制的計數。這裡上一道模板題 題中就是要你統計1 n裡有 49 的個數。dp pos sta 表示到第pos位,狀態為sta的總數。我們一般是從...

模板 動態規劃 區間dp

因為昨天在codeforces上設計的區間dp錯了 錯過了上紫的機會 覺得很難受。看看學長好像也有學,就不用看別的神犇的了。區間dp處理環的時候可以把序列延長一倍。for int len 1 len n len 首先,使用四邊形優化要滿足下面的性質 當小區間包含在大區間中,則小區間的成本不高於大區間...

動態規劃 數字dp入門(二)

較為簡單的數字dp只會涉及到每一位上的數字變化,如比較相鄰數字差,是否含有某個數字等等,在這種情況下一般用dp i j 就可以,i表示數字長度,j用來表示首位數字。如果題目要求對數字整體進行考慮,我們不能對各個位置上的數直接判斷,就需要對每位之前判斷過的數進行記憶化儲存。題目hdu3652 numb...