HDU2089 (不要62)——简单数位DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089
不要62
Time Limit: 1000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有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
题意:给定一段数,比如说 [1 ,100],就是求1到100之间没有含有62和4的数的个数。
首先说它是DP,倒不如说是深搜套一个记忆化的壳。在深搜之前,需要把数拆成数组,然后我们记录取到第k位,要取之后的n-k个数的方案数(不考虑是否超过范围),以及取到这一位的状态(视题意而定)。深搜的过程中,要传下下面几个参数:k、if6、limit,分别代表取到第几位,目前的状态,数的上界。
以下就是我的代码:
1 #include<stdio.h> 2 #inclufe<string.h>; 3 int dp[20][2]; 4 int shu[20]; 5 int n,m; 6 int dfs(int len,bool if6,bool limit)//if6=>上一位是否为6 limit=>它的上一位是否为上界 len表示num的位数 7 { 8 if(len==0) //当len=1是边界,所以在len=0时,return 9 return 1; 10 if(!limit && dp[len][if6]) 11 return dp[len][if6]; 12 int sum=0; //没有62和4的数量 13 int max=(limit?shu[len]:9); 14 for(int i=0;i<=max;i++) 15 { 16 if((if6&&i==2)||i==4)//剪枝 减去62和4的那一枝 17 continue; 18 sum+=dfs(len-1,i==6,limit&&i==max); 19 } 20 if(!limit) 21 dp[len][if6]=sum; //这里对应上面的记忆化,在一定条件下下时记录,保证一致性。 22 return sum; 23 } 24 int solve(int num) //将num的数位分开来 25 { 26 memset(shu,0,sizeof(shu)); 27 int k=0; 28 while(num) 29 { 30 shu[++k]=num%10; 31 num/=10; 32 } 33 return dfs(k,false,true); 34 } 35 int main() 36 { 37 while(scanf("%d%d",&n,&m)!=EOF) 38 { 39 memset(dp,0,sizeof(dp)); 40 if(n==0&&m==0) 41 return 0; 42 int ans; 43 ans=solve(m)-solve(n-1);//因为是取[n,m]内的数,所以只需要减去[0,n-1]内的数 44 printf("%d\n",ans); 45 } 46 return 0; 47 }

浙公网安备 33010602011771号