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

2021-07-23 13:25:35 字數 1820 閱讀 6082

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

題目hdu3652 number

題意是讓你求範圍內出現13且能被13整除的數的個數。

#include#include#include#includeusing namespace std;

int num[15],len,maxlen;

int dp[20][13][3];

//dp[i][j][k]表示i位數,對13的餘數是j

//k為0表示沒有出現13

//k為1表示沒有出現13,但是首位為3

//k為2表示出現13

int dfs(int len,int first,int mod,bool flag,bool ok)// len長度,first第乙個數,mod取的模,flag到達上個位置的最大值,ok已經有13

if(!flag)

return sum;

}int shudp(int number)

maxlen = len;

return dfs(len,0,0,true,false);

}int main()

由這個例題可以得出乙個解這種涉及到資料本身的數字dp的基本步奏:

(1).在shudp()函式中將該數分解儲存。

(2).由dfs()函式進行主要求解。

其中dfs()函式中,會讀取每次的len(數字長度)來進行在數字上的遍歷(如萬,千,百...)最後停止dfs()。還會有乙個對該數字數值是否到達最大的bool型(即該例題中的flag),乙個對針對題意的限制條件(即該例題中的 ok ).

將這個dfs過程可以細分為幾個區域:

這一塊是在dfs()過程中對sum的累加。

if(len <= 0)

return ok&&(mod==0); //如果已經出現了13,而且餘數為0,返回1,否則為0

if(!flag && ok && dp[len][mod][0]!=-1)

return dp[len][mod][0]; //已經出現13且前一位不是最大值,那麼後面就可以直接取長度

if(!flag && !ok && dp[len][mod][2]!=-1 && first!=1)

return dp[len][mod][2];

if(!flag && !ok && dp[len][mod][1]!=-1 && first==1)

return dp[len][mod][1]; //之前沒有13,但是末位是1,那麼後面的高位可以是3

int over;

if(!flag) // 如果沒取到這個位置的最大值,則下一位可取到9

over = 9;

else

over = num[len];

這一塊是算出下一位能達到的值的最大值。

int sum = 0;

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

這一塊是dfs()的遞迴部分,每一次的dfs()都在這裡暫停,進入下一次的dfs()中,直至結束。

if(!flag)

return sum;

這一塊dfs()進行到最後,開始對dp陣列處理,return之後開始回溯,不停的return,直至到最開始的dfs。

動態規劃之數字dp

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

模板 動態規劃 數字dp

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 可能需要的狀...

C 入門DP 動態規劃

本篇為入門級,dalao繞道 捂臉 dp最經典題目 01揹包問題 思路簡單清晰,將物品和價值都遍歷,進行選擇 for int i 1 i n i 從第乙個物品到最後乙個物品遍歷 cout dp n m endl 優化 時間複雜度不變,降低了空間複雜度 for int i 1 i n i for in...