較為簡單的數字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...