动态规划-数位DP
文章目录
- 数位DP
- 例题
- HDU-2089
- 法一、递推公式
- 法二、记忆化搜索
- HDU-3555
- 法一
- 法二
数位DP
例题
HDU-2089
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
法一、递推公式
#include<bits/stdc++.h>
using namespace std;
int a[20];
int dp[20][10];
void init(){
dp[0][0] = 1;
for (int i = 1; i <= 7; i++)//题目交代7位数
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];
}
int solve(int x){
int pos = 0;
int ans = 0;
while (x) {
a[++pos] = x % 10;
x /= 10;
}
a[pos + 1] = 0;
for (int i = pos; i >= 1; i--){//枚举位数
for (int j = 0; j < a[i]; j++) {//枚举首位
if (a[i + 1] != 6 || j != 2)
ans += dp[i][j];
}
if (a[i] == 4 || (a[i + 1] == 6 && a[i] == 2))
break; //只要含4或62后面的都不统计了
}
return ans;
}
int main() {
init();
int n, m;
while (~scanf("%d%d", &n, &m) && (n + m)) {
printf("%dn", solve(m + 1) - solve(n));
}
return 0;
}
法二、记忆化搜索
#include<bits/stdc++.h>
using namespace std;
int a[20];
int dp[20][2];
int dfs(int pos, int pre, int sta, bool limit){
if (pos == -1)
return 1;
if (!limit && dp[pos][sta] != -1) //记忆
return dp[pos][sta];
int up = limit ? a[pos] : 9;
int temp = 0;
for (int i = 0; i <= up; i++){
if (i == 4)
continue;
if (pre == 6 && i == 2)
continue;
temp += dfs(pos - 1, i, i == 6, limit && i == a[pos]);
}
if (!limit)
dp[pos][sta] = temp;
return temp;
}
int solve(int x){
int pos = 0;
while (x){
a[pos++] = x % 10;
x /= 10;
}
return dfs(pos - 1, -1, 0, true);
}
int main(){
int n, m;
while (~scanf("%d%d", &n, &m) && (n + m)){
memset(dp, -1, sizeof(dp));
printf("%dn", solve(m) - solve(n - 1));
}
return 0;
}
HDU-3555
Problem Description The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence “49”, the power of the blast would add one point. Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them? Input The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description. The input terminates by end of file marker. Output For each test case, output an integer indicating the final points of the power. Sample Input 3 1 50 500 Sample Output 0 1 15 Hint From 1 to 500, the numbers that include the sub-sequence “49” are “49”,“149”,“249”,“349”,“449”,“490”,“491”,“492”,“493”,“494”,“495”,“496”,“497”,“498”,“499”, so the answer is 15.
求1-n有多少个含49的数,是上一题的反面,去不含49即可。
法一
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
ll a[100];
ll dp[100][10];
void init() {
dp[0][0] = 1;
for (int i = 1; i <= 63; i++)
for (int j = 0; j <= 9; j++)
for (int k = 0; k <= 9; ++k)
if (!(j == 4 && k == 9))
dp[i][j] += dp[i - 1][k];
}
ll solve(ll x) {
int pos = 0;
ll ans = 0;
while (x) {
a[++pos] = x % 10;
x /= 10;
}
a[pos + 1] = 0;
for (int i = pos; i >= 1; i--) {
for (int j = 0; j < a[i]; j++) {
if (a[i + 1] != 4 || j != 9)
ans += dp[i][j];
}
if (a[i + 1] == 4 && a[i] == 9)
break;
}
return ans;
}
int main() {
init();
ll t, n;
scanf("%lld", &t);
while (t--) {
scanf("%lld", &n);
printf("%lldn", n + 1-solve(n + 1));
}
return 0;
}
法二
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
ll a[100];
ll dp[100][2];
ll dfs(int pos, int pre, int sta, bool limit) {
if (pos == -1)
return 1;
if (!limit && dp[pos][sta])
return dp[pos][sta];
int up = limit ? a[pos] : 9;
ll temp = 0;
for (int i = 0; i <= up; i++) {
if (pre == 4 && i == 9)
continue;
temp += dfs(pos - 1, i, i == 4, limit && i == a[pos]);
}
if (!limit)
dp[pos][sta] = temp;
return temp;
}
ll solve(ll x) {
int pos = 0;
while (x) {
a[pos++] = x % 10;
x /= 10;
}
return dfs(pos - 1, -1, 0, true);
}
int main() {
ll t, n;
scanf("%lld", &t);
while (t--) {
scanf("%lld", &n);
memset(dp, 0, sizeof(dp));
printf("%lldn", n + 1 - solve(n));
}
return 0;
}
原创不易,请勿转载(
本不富裕的访问量雪上加霜) 博主首页:https://blog.csdn.net/qq_45034708
- MySQL日志文件之错误日志和慢查询日志详解
- 采用HTML5之"data-"机制自由提供数据
- Spring和SpringMVC父子的容器之道---[上篇]
- 快速完成(图片旋转,查看原图)
- Jsp中格式化时间戳的常用标签
- 反射+自定义注解---实现Excel数据列属性和JavaBean属性的自动映射
- 后台模板管理系统___左侧菜单数据的异步加载
- Shiro眼皮下玩ajax,玩出302 Found
- 对于JSONObject,我只是临时抱佛脚
- 总结切面编程AOP的注解式开发和XML式开发
- SpringMVC注解@RequestMapping之produces属性导致的406错误
- SpringBoot集成MyBatis的分页插件PageHelper(回头草)
- SpringBoot整合Mybatis之进门篇
- Tomcat和Java Virtual Machine的性能调优总结
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- MySQL 快速删除大量数据(千万级别)的几种实践方案——附源码
- 什么样的代码是好代码?
- Elastic search集群新增节点(同一集群,同一物理机)
- Tesseract-OCR 4.1.0 安装和使用— windows及CentOS
- Java 大小端转换(基于ByteBuffer)
- Tika结合Tesseract-OCR 实现光学汉字识别(简体、宋体的识别率百分之百)—附Java源码、测试数据和训练集下载地址
- 阿里《JAVA实习生入职测试题—2019最新》之答案详解(连载一)
- 阿里《JAVA实习生入职测试题—2019最新》之答案详解(连载二)
- 动态生成RDLC报表
- Angular 页面元素的DOM级别的删除过程
- 单例模式—四种写法详解
- Angular view container删除view实例的过程
- Angular自定义structural指令的实例化过程以及set方法的调用
- Angular structural指令host element的定位调试
- Import-Module ServerManager Import-Module : 未能加载指定的模块“ServerManager”,因为在任何模块目录中都没有找到有效模块文件..