[关闭]
@xingxing 2017-02-18T03:31:41.000000Z 字数 1062 阅读 664

专题七 动态规划

题解动态规划


[题目][A]

数位dp

题目大意:

输出[n,m]区间中的吉利数字的个数。(0 < n <= m < 1000000)吉利数字是数字钟不含4和62的数。当n,m均为0时,输入结束。

解题思路:

数位dp。[n,m]的范围可以由(0,m+1)-(0,n)得到,即求这两个范围里的吉利数然后相减。
统一的做法来求(0,n)范围内的吉利数,用dp[i][j]来表示以j开头的i位数,有多个,这些j开头的i位数为吉利数有多少个。
dp[i][j]的意义下,我们可以处理到每位数,当符合要求时,dp[i][j] += dp[i-1][k],(k为i-1位数的开头的数)。
然后将n,m分别输入处理,把每一位数分解出来,通过小于对应位数的该位的数的列举,然后把符合条件的以j开头的i位数的dp[i][j]加起来,就是答案。如果某位数处理完后,发现该位及其前缀已经不符合条件,那么后面再进行下去,也没有意义。(数位处理的要点,处理以j开头的i位数,超出i位数的保持原数据不变,只处理这i位数)
时间复杂度O(1),空间复杂度O(1).

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. int dp[10][10];
  6. void init()
  7. {
  8. int i,j,k;
  9. memset(dp,0,sizeof(dp));
  10. dp[0][0] = 1;
  11. for(i = 1;i <= 7;i++)
  12. {
  13. for(j = 0;j <= 9;j++)
  14. {
  15. for(k = 0;k <= 9;k++)
  16. {
  17. if(j != 4 && !(j == 6 && k == 2))
  18. {
  19. dp[i][j] += dp[i-1][k];
  20. }
  21. }
  22. }
  23. }
  24. }
  25. int solve(int n)
  26. {
  27. int num[10];
  28. int len = 0;
  29. int i,j;
  30. int ans = 0;
  31. init();
  32. while(n > 0)
  33. {
  34. num[++len] = n%10;
  35. n /= 10;
  36. }
  37. num[len+1] = 0;
  38. for(i = len;i >= 1;i--)
  39. {
  40. for(j = 0;j < num[i];j++)
  41. {
  42. if(j != 4 && !(num[i+1] == 6 && j == 2))
  43. ans += dp[i][j];
  44. }
  45. if(num[i] == 4 || (num[i] == 2 && num[i+1] == 6))
  46. break;
  47. }
  48. return ans;
  49. }
  50. int main()
  51. {
  52. int n,m;
  53. while(scanf("%d%d",&n,&m) != EOF && !(n == 0 && m == 0))
  54. {
  55. printf("%d\n",solve(m+1) - solve(n));
  56. }
  57. return 0;
  58. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注