1. 程式人生 > >hdu--2089 不要62(數位DP的入門題目)

hdu--2089 不要62(數位DP的入門題目)

題目連結:不要62

不要62
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 53366 Accepted Submission(s): 20401

Problem Description
杭州人稱那些傻乎乎粘嗒嗒的人為62(音:laoer)。
杭州交通管理局經常會擴充一些的士車牌照,新近出來一個好訊息,以後上牌照,不再含有不吉利的數字了,這樣一來,就可以消除個別的士司機和乘客的心理障礙,更安全地服務大眾。
不吉利的數字為所有含有4或62的號碼。例如:
62315 73418 88914
都屬於不吉利號碼。但是,61152雖然含有6和2,但不是62連號,所以不屬於不吉利數字之列。
你的任務是,對於每次給出的一個牌照區間號,推斷出交管局今次又要實際上給多少輛新的士車上牌照了。

Input
輸入的都是整數對n、m(0< n≤m<1000000),如果遇到都是0的整數對,則輸入結束。

Output
對於每個整數對,輸出一個不含有不吉利數字的統計個數,該數值佔一行位置。

Sample Input
1 100
0 0

Sample Output
80

Author
qianneng

Source
迎接新學期——超級Easy版熱身賽

思路:這是一道數位DP的入門題目,我也是剛做的(要學學DP了),可能講的不是很清楚。

數位DP就是在數位上進行操作的,例如:245 我們會記錄他的每一位,a[2]=2,a[1]=4,a[0]=5.
首先有兩中情況,62和4,是不能出現的,所以我們只用記錄在沒有限制的情況下,前一位是不是6(這是用來記錄6開頭的和非6開頭的,4這種情況我們是不會找的,所以不用記錄),開一個二維陣列記錄dp[len][2],len記錄查詢的這個數有多長(有多少位),2分為兩種(6開頭的和非6開頭的情況),dp 只會記錄沒有前一位數字限制的情況下的種數,因為沒有前一位的限制情況數是一定的,這樣方便其他數的查詢。

具體的可以看程式碼:

#include<stdio.h>
#include<string.h>
#define mem(a,b) memset(a,b,sizeof(a))

const int maxn=20;//數最多有多長
int dp[maxn][2];
int a[maxn];

int dfs(int i,int pre,int j,int limit)
{
    if(i==-1) return 1;//查到頭了,說明這是其中的一種情況。

    if(!limit&&dp[i][j]!=-1)//如果沒有前面的限制並且dp[i][j]這種情況已經被記錄過了,直接返回 
return dp[i][j]; int ans=0; int up=limit?a[i]:9;//在判斷這一位最高能放數字幾。 for(int k=0;k<=up;k++)//遍歷每一個能放的數字 { if(k==4) continue; if(k==2&&pre==6) continue;//以上兩種不可取 ans+=dfs(i-1,k,k==6,limit&&k==a[i]);//深搜並更新狀態 } if(!limit) dp[i][j]=ans;//只有沒有限制的時候才記錄個數 return ans; } int solve(int x) { int len=0; while(x) { a[len++]=x%10; x/=10; } return dfs(len-1,-1,0,1);//dfs(從查詢數的最高位開始列舉,記錄前一位是幾,記錄前一位是不是6,有沒有限制)。 } int main() { int n,m; mem(dp,-1);//這裡只用初始化一次即可。 while(~scanf("%d%d",&n,&m),n+m) { printf("%d\n",solve(m)-solve(n-1)); } return 0; }