引言
數字dp的實質還是「列舉」,但利用記憶化搜尋的方式使其具有dp的性質,從而降低了時間複雜度
基礎 數字dp解決的問題一般型別是:統計乙個區間[le,ri]內滿足一些條件數的個數,如果暴力列舉即為:
int ans=0;
for(int i=le;i<=ri;++i)
if(solve(i)) ans++;
可見當le,ri差值較大時(如》1e8),暴力列舉是行不通的。
數字dp「列舉」的思路大致就是:
按照乙個數字位數的高低,由高到底進行處理、列舉,並根據不同的狀態(題意)進行記憶化操作(關鍵)。
其中stata變數的轉移最為重要,也是dp的精華所在。不同背景下,轉移方程(分類轉移等)和記憶化方式(陣列維數等)是多變的。 模板
typedef long long ll;
int a[20];
ll dp[20][state];//不同題目狀態不同
ll dfs(int pos,/*state 變數*/,bool lead,/*前導零*/,bool limit/*數字上界變數*/)
//計算完,記錄狀態
if(!limit&&!lead) dp[pos][state]=ans;
/*這裡對應上面的記憶化,在一定條件下時記錄,保證一致性,
如果約束條件不需要考慮lead,這裡就是lead就完全不用考慮了*/
return ans;
}ll solve(ll x)
return dfs(pos-1,/*狀態*/,true,true);//剛開始傳參最高位都是有限制並且有前導零的,比最高位還要高的一位視為0
}int main()
return 0;
}
例題 hd 2089
problem description
杭州人稱那些傻乎乎粘嗒嗒的人為62(音:laoer)。
杭州交通管理局經常會擴充一些的士車牌照,新近出來乙個好訊息,以後上牌照,不再含有不吉利的數字了,這樣一來,就可以消除個別的士司機和乘客的心理障礙,更安全地服務大眾。
不吉利的數字為所有含有4或62的號碼。例如:
62315 73418 88914
都屬於不吉利號碼。但是,61152雖然含有6和2,但不是62連號,所以不屬於不吉利數字之列。
你的任務是,對於每次給出的乙個牌照區間號,推斷出交管局今次又要實際上給多少輛新的士車上牌照了。
input
輸入的都是整數對n、m(0
output
對於每個整數對,輸出乙個不含有不吉利數字的統計個數,該數值佔一行位置。
sample input
1 1000 0
sample output
80
**示例
//#define local
#include#include#include#include#include#include#includeusing namespace std;
int a[20];
int dp[20][2];
int dfs(int pos,int pre,int sta,bool limit)
if(!limit) dp[pos][sta]=tmp;
return tmp;
}int solve(int x)
return dfs(pos-1,-1,0,true);
}int main()
return 0;
}
一種更好理解的寫法
#includeconst int maxn=10;
long long f[maxn][10];
void getdp()
else}}
}int a[maxn];
long long solve(int n)
a[a[0]+1]=0;
long long ans=0;
for (int i=a[0];i>=1;i--)
{for (int j=0;j
樹形DP初探 總結
這幾天,我自學了基礎的樹形dp,在此給大家分享一下我的心得。首先,樹形dp這種題主要就是解決有明確分層次且無環的樹上動態規劃的題。這種題型一般 注意只是基礎 普通的情況下 用深度優先搜尋來解決實際的dp部分,而且一般用記憶化搜尋,因為樹會有重複遍歷節點的情況。在一棵樹上針對普遍子樹都滿足根節點與兩個...
數字DP入門 數字DP模板
數字dp是一種計數用的dp,一般就是要統計乙個區間 le,ri 內滿足一些條件數的個數。所謂數字dp,字面意思就是在數字上進行dp咯。數字還算是比較好聽的名字,數字的含義 乙個數有個位 十位 百位 千位.數的每一位就是數字啦!之所以要引入數字的概念完全就是為了dp。數字dp的實質就是換一種暴力列舉的...
數字dp模版(dp)
1 include 2 include 3 include 4 include 5 6using namespace std 78 intt 9long long dp 19 19 2005 10 long long l,r 11int shu 20 12 13long long dfs int l...