數位DP入門
阿新 • • 發佈:2021-10-07
數位DP入門(蒟蒻)
概念
所謂數位DP就是指的數位DP,就是對數字的每一位進行DP 。
我們在具體例題中來分析數位DP
P2657 SCOI2009windy數
題目描述
不含前導零且相鄰兩個數字之差至少為 2 的正整數被稱為 windy 數。windy 想知道,在 a 和 b之間,包括 a 和 b ,總共有多少個 windy 數?
輸入格式
輸入只有一行兩個整數,分別表示 a 和 b
輸出格式
輸出一行一個整數表示答案。
輸入1
1 10
輸出1
9
輸入2
25 50
輸出2
20
分析
我們將n的每一位拆分開分別計算它的貢獻,從最高位依次固定,設
f[i][j] 表示一共i位,最高位是j的windy數的個數
程式碼
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <vector> using namespace std; typedef long long ll; const int N = 11; int f[N][10];//f[i][j] 表示一共i位,最高位是j的windy數個數 void init() { for(int i=0;i<=9;i++) f[1][i] = 1;//個位數可以取10個 for(int i=2;i<N;i++) { for(int j=0;j<=9;j++) for(int k=0;k<=9;k++) if(abs(j - k) >= 2) f[i][j] += f[i-1][k]; } } int l,r; int dp(int n) { if(n == 0) return 0; vector<int> v; while(n) v.push_back(n % 10),n /= 10;//提取每一位 int res = 0; int last = -2; for(int i=v.size()-1;i>=0;i--) { int x = v[i]; for(int j = i == v.size() - 1;j < x; j++) { if(abs(j - last) >= 2) res += f[i+1][j]; } if(abs(x - last) >= 2) last = x; else break; if(i == 0) res++; } for(int i=1;i<v.size();i++) for(int j=1;j<=9;j++) res += f[i][j]; return res; } int main() { init(); cin>>l>>r; cout<<dp(r) - dp(l - 1); return 0; }