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 }

 

posted @ 2015-01-26 13:08  Naturain  阅读(116)  评论(0编辑  收藏  举报