HDU 2089 数位dp 不要62

来源:互联网 发布:js定义json数组并赋值 编辑:程序博客网 时间:2024/06/05 17:11

不要62

题目链接:传送门

其实是做topcoder的时候碰到不会的题,看人家说要用数位dp,所以拿http://acm.hdu.edu.cn/showproblem.PHP?pid=2089来学习了一下

数位dp适合在一段数的区间内找出满足某些条件的数的个数,这个时候往往不能之间遍历,肯定会超时,则一般使用数位dp来解决

数位dp的常见形式是dp[i][j],表示开头是j的i位数满足条件的有多少个,当然也有其他dp[i][j][k]等等,但i,j,k都很小,不会像直接遍历那么耗时

像这道题的话,知道了dp[i][j]表示的是啥,就能列出状态转移方程(稍微认真看就能理解的):

[cpp] view plain copy
  1. for(int i=1;i<=7;i++)  
  2.     {  
  3.         for(int j=0;j<10;j++)//枚举第i位可能出现的数  
  4.         {  
  5.             for(int k=0;k<10;k++)//枚举第i-1位可能出现的数  
  6.             {  
  7.                 if(j!=4&&!(j==6&&k==2))  
  8.                     dp[i][j]  += dp[i-1][k];  
  9.             }  
  10.         }  
  11.     }  



 

更加具体的介绍可以参考:http://wenku.baidu.com/link?url=o3ER_gVCyB0qcKthM-Y8vPtAGZ_u5bzOu_gUCUhPcXC6YfaSDgtBSXNEEvvGvSzyuDE9TULcPNsDrRd9IUtQVHeKUVrnPUjyfWjCly_J7Xq


以下附上ac这题的代码:

[cpp] view plain copy
  1. #include <iostream>  
  2. #include <string>  
  3. #include <string.h>  
  4. #include <algorithm>  
  5. using namespace std;  
  6. int dp[10][10];  
  7. void init()  
  8. {  
  9.     memset(dp,0,sizeof(dp));  
  10.     dp[0][0] = 1;  
  11.     for(int i=1;i<=7;i++)  
  12.     {  
  13.         for(int j=0;j<10;j++)//枚举第i位可能出现的数  
  14.         {  
  15.             for(int k=0;k<10;k++)//枚举第i-1位可能出现的数  
  16.             {  
  17.                 if(j!=4&&!(j==6&&k==2))  
  18.                     dp[i][j]  += dp[i-1][k];  
  19.             }  
  20.         }  
  21.     }  
  22. }  
  23. int solve(int n)  
  24. {  
  25.     init();  
  26.     int digit[10];  
  27.     int len = 0;  
  28.     while(n>0)  
  29.     {  
  30.         digit[++len] = n%10;  
  31.         n/=10;  
  32.     }  
  33.     digit[len+1]=0;  
  34.     int ans = 0;  
  35.     for(int i=len;i;i--)  
  36.     {  
  37.         for(int j=0;j<digit[i];j++)  
  38.         {  
  39.             if(j!=4&&!(digit[i+1]==6&&j==2))  
  40.                 ans+=dp[i][j];  
  41.         }  
  42.         if(digit[i]==4||(digit[i]==2&&digit[i+1]==6))  
  43.             break;  
  44.     }  
  45.     return  ans;  
  46. }  
  47. int main()  
  48. {  
  49.     int l,r;  
  50.     while(cin>>l>>r)  
  51.     {  
  52.         if(l+r==0)  
  53.             break;  
  54.         else  
  55.             cout<<solve(r+1)-solve(l)<<endl;  //因为solve没有考虑r的情况所以要从r+1开始才是正确结果。
  56.     }  
  57.     return 0;  
  58.   
  59. }  

0 0
原创粉丝点击