hdu 2089 入手数位dp问题
数位dp解决的问题是指求在一段数的区间里面 满足条件的数的个数
核心为两点
http://wenku.baidu.com/link?url=tpfIYzhx_MzevpIM58UZ66pr-87MCFPKTMKFdGDi5jUqyO9ckti0mY6diSz2PZEL_ZBhd2zIbhus1mnzDiAO1B5K2Vu38YDsqjmOvYKFT6q
我自己总结下吧
第一 是dp的状态转移方程
dp[i][j] 表示的是以j开头的i位数 满足条件的个数为多少
既然是要记录满足条件的个 那么 dp[i][j]=sum(dp[i-1][0~9]) 这个不难理解
for(int i=1;i<=7;i++) { for(int j=0;j<=9;j++) { for(int k=0;k<=9;k++) { if(j!=4&&!(j==6&&k==2)) dp[i][j]+=dp[i-1][k]; } } }
然后就是solve函数问题 solve(i)这个函数的作用是求出【0,i)区间满足条件的数的个数
大致的思想 是从高位开始 逐一枚举比该为数小的数 在满足的条件的情况下 统计和 每次枚举完
举完一位以后 由于是列举比n小的数 所以 每一位枚举结束后 就需要将这个位定下来
花了不少时间入门。。继续干!
#include<cstdio> #include<iostream> #include<string.h> using namespace std; int dp[11][11]; int solve(int n) { int dig[10],len=0; memset(dig,0,sizeof(dig)); while(n>0) { dig[++len]=n%10; n=n/10; } dig[len+1]=0; int ans=0; for(int i=len;i;i--)//这里的思想 从最高位开始枚举 枚举完一位以后 由于是列举比n小的数 所以 每一位枚举结束后 就需要将这个位定下来 { for(int j=0;j<dig[i];j++) { if(j!=4&&!(dig[i+1]==6&&j==2))//判断此时的枚举是否合法 ans+=dp[i][j]; } if(dig[i]==4||(dig[i+1]==6&&dig[i]==2)) break;//之前位置定好了 如果出现了不满足条件的情况 后面继续下去就没有什么意思了 } return ans; } int main() { int n,m; while(cin>>n>>m) { if(m+n==0) break; memset(dp,0,sizeof(dp)); dp[0][0]=1; for(int i=1;i<=7;i++) { for(int j=0;j<=9;j++) { for(int k=0;k<=9;k++) { if(j!=4&&!(j==6&&k==2)) dp[i][j]+=dp[i-1][k]; } } } cout<<solve(m+1)-solve(n)<<endl;// 这里要不要加1是要考虑区间的开闭情况 } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!