hdu 3555 Bomb(数位dp)
Posted jpphy0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 3555 Bomb(数位dp)相关的知识,希望对你有一定的参考价值。
问题
hdu 3555 Bomb - https://acm.hdu.edu.cn/showproblem.php?pid=3555
分析
状态转移
从低位到高位
- 注意:图中的最高位是指当前已构造部分的最高位,并非指最终的最高位
从高位到低位
- 注意:图中的最低位是指当前已构造部分的最低位,并非指最终的最低位
“高 ⇒ \\Rightarrow ⇒ 低”枚举
- 例如:求
5495
高
位
←
低
位
\\overset{高位 \\leftarrow 低位}{5495}
5495高位←低位以内的不含49的数字个数(包含:0000)
- 最高高位取0时,则可取0999 - 0000内所有不含49的数
- 最高高位取1时,则可取1999 - 1000内所有不含49的数
- 最高高位取2时,则可取2999 - 2000内所有不含49的数
- 最高高位取3时,则可取3999 - 3000内所有不含49的数
- 最高高位取4时,则可取4999 - 4000内所有不是9开头的不含49的数
- 最高高位取5时,则可取5495 - 5000内所有不含49的数
- 如何求0999 - 0000、1999 - 1000、2999 - 2000、3999 - 3000、4999 - 4000、5495 - 5000内满足要求的数呢?
- 0999 - 0000、1999 - 1000、2999 - 2000、3999 - 3000:所有999 - 000内的不含49的数
- 4999 - 4000:所有999 - 000内的不是9开头的不含49的数(注意:90应看作090,不能看作以9开头)
- 5495 - 5000:所有495 - 000内的不含49的数
- 495 - 000是一个受限的3位数,而999 - 000 是一个不受限的3位数
dfs设计
- 四类子问题
- 不受限的m位不含49的数字个数【包含了9开头的不含49的数字】
- 不受限的m位不是9开头的不含49的数字个数
- 受限的m位不含49的数字个数【包含了9开头的不含49的数字】
- 受限的m位不是9开头的不含49的数字个数(例如:495 - 000)
- 参数
- 数字位数, m m m
- 是否受限, i s m a x ismax ismax
- 是否包含9开头的不含49的数字, i s 4 is4 is4
- 功能
- 返回相应条件下的数字个数
- 1、2两类子问题与状态表关系紧密,可以查表,也可以对表赋值
状态设计
- 采用从低位到高位转移的方式
-
d
p
[
n
]
[
s
t
a
t
e
]
dp[n][state]
dp[n][state]:长度n位的数字在state条件下 不 含49的数字个数
- state = 0,表示所有不含49的数字个数,对应了dfs的第1类子问题
- state = 1,表示最高位不是9的不含49的数字个数,对应了dfs的第2类子问题
- dp数组 仅 初始化 一次,也就是说状态表被多个测试样例 共享
代码
/* hdu 3555 Bomb 数位dp*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MXN = 25;
int n, b[MXN];
ll dp[MXN][2];
ll dfs(int m, int is4, bool ismax){
if(m == 0) return 1;
if(!ismax && ~dp[m][is4]) return dp[m][is4];
ll ans = 0, end = ismax?b[m]:9;
for(int i = 0; i <= end; ++i){
if(is4 && i == 9) continue;
ans += dfs(m-1, i == 4, ismax && i == end);
}
if(!ismax) dp[m][is4] = ans;
return ans;
}
int main(){
int t;
ll N;
scanf("%d", &t);
以上是关于hdu 3555 Bomb(数位dp)的主要内容,如果未能解决你的问题,请参考以下文章