HDU--2089(数位DP,基础)
2015-01-26 13:03:58
思路:数位DP基础题。
算出1~m中的可用车牌数减去1~n-1的可用车牌数。
采用记忆化搜索解决,从高位开始往低位考虑,参数有三个:(1)当前放哪一位(2)前一位是什么数(就是比它高一位的数)(3)是否已经比当前范围数小。
注意:当前位不能放4,如果前一位为6那么当前位不能放2,如果已经比范围数小(如果当前求1~m,那么m为范围数),那么该位没有限制,否则当前位放的数不能超过范围数的第p位。
dp[i][j][k]表示放第i位,前一位为j,k表示是否已经小于范围数。(最高位视为第1位)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <string> 11 #include <iostream> 12 #include <algorithm> 13 using namespace std; 14 15 #define MEM(a,b) memset(a,b,sizeof(a)) 16 #define REP(i,n) for(int i=1;i<=(n);++i) 17 #define REV(i,n) for(int i=(n);i>=1;--i) 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 20 #define MP(a,b) make_pair(a,b) 21 22 typedef long long ll; 23 typedef pair<int,int> pii; 24 const int INF = (1 << 30) - 1; 25 26 int n,m; 27 int dp[10][10][2]; 28 int di[10],cnt; 29 30 int Dfs(int p,int pre,int flag){ 31 if(p <= 0) 32 return 1; 33 if(dp[p][pre][flag] != -1) 34 return dp[p][pre][flag]; 35 int res = 0,top = (flag == 1) ? 9 : di[p]; 36 FOR(i,0,top){ 37 if(i == 4 || (i == 2 && pre == 6)) 38 continue; 39 res += Dfs(p - 1,i,flag || i < di[p]); 40 } 41 return dp[p][pre][flag] = res; 42 } 43 44 int Solve(int v){ 45 MEM(dp,-1); 46 cnt = 0; 47 while(v){ 48 di[++cnt] = v % 10; 49 v /= 10; 50 } 51 return Dfs(cnt,0,0); 52 } 53 54 int main(){ 55 while(scanf("%d%d",&n,&m) != EOF){ 56 if(!n && !m) break; 57 if(n > m){ n = n ^ m , m = n ^ m , n = n ^ m;} 58 printf("%d\n",Solve(m) - Solve(n - 1)); 59 } 60 return 0; 61 }