hdu3555 Bomb 【数位dp+记忆化dfs】
来源:互联网 发布:淘宝客服团队建设 编辑:程序博客网 时间:2024/06/05 03:58
题目链接:hdu3555 Bomb
题意:
t组样例,给正整数n
1. 传统dp
dp预处理出
注意n包括49的情况, 例如n=234950这种情况, 49之后不再按每位值累加,而是[234900, 234950]都符合。
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;typedef long long LL;int a[25];LL dp[25][3];//dp[i][0] len <= i && 包含 49 的个数//dp[i][1] len = i && 首位是 9 && 不包含 49 的个数//dp[i][2] len <= i && 不包含 49 的个数void init(){ memset(dp, 0, sizeof(dp)); dp[0][2] = 1; for(int i = 1; i < 22; i++) { //转移方程 dp[i][0] = 10 * dp[i-1][0] + dp[i-1][1]; dp[i][1] = dp[i-1][2]; dp[i][2] = 10 * dp[i-1][2] - dp[i-1][1]; }}LL sol(LL x){ int w = 0; x++; //答案没有算自身,统计的是(1, n)开区间,可以变为统计(1,n+1); 或者返回答案时特判+1。 while(x) { a[++w] = x % 10; x /= 10; } a[w+1] = 0; LL ans = 0; int flag = false; //flag 表示前几位中是否存在49 for(int i = w; i > 0; i--) { ans += a[i] * dp[i-1][0]; if(flag) //前几位存在49时 剩余位全都符合 ans += a[i]*1e(i-1) //因为1e(i-1)可以拆成dp[i-1][0]+dp[i-1][2], 只需再加上dp[i-1][2] ans += a[i] * dp[i-1][2]; else //不存在49时 0~a[i]-1已考虑 即为a[i]*dp[i-1][0],只需再考虑a[i]的情况 { if(a[i] > 4) //a[i]>4时 i位可以为4和i-1位为9且不含49的情况组合 一共dp[i-1][1]个 ans += dp[i-1][1]; if(a[i+1] == 4 && a[i] == 9) //出现49 标记 flag = true; } } //if(flag) ans++; return ans;}int main(int argc, char const *argv[]){ init(); int t; scanf("%d", &t); while(t--) { LL n; scanf("%lld", &n); printf("%lld\n", sol(n)); } return 0;}
2. 记忆化dfs
刚学的记忆化搜索写法,看了好久才理解,注意dp数组意义与传统dp中的不相同。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;int bit[25];LL dp[25][3];//第一维对应st = 0, 1, 2 三种情况//第二维对应位数LL dfs(int pos, int st, bool flag)//pos:当前位数//st: 高位状态 st=0: 没有49; st=1: 前一位为4; st=2: 前几位中有49。//flag:高位是否不是原数{ if(pos == 0) return st == 2; if(flag && dp[pos][st] != -1) return dp[pos][st]; LL ans = 0; int x = flag? 9: bit[pos]; for(int i = 0; i <= x; i++) { if(st == 2 || st == 1 && i == 9) ans += dfs(pos-1, 2, flag || i < x); else if(i == 4) ans += dfs(pos-1, 1, flag || i < x); else ans += dfs(pos-1, 0, flag || i < x); } if(flag) dp[pos][st] = ans; return ans;}LL sol(LL x){ int len = 0; while(x) { bit[++len] = x % 10; x /= 10; } return dfs(len, 0, false);}int main(int argc, char const *argv[]){ int t; memset(dp, -1, sizeof(dp)); scanf("%d", &t); while(t--) { LL x; scanf("%lld", &x); printf("%lld\n", sol(x)); } return 0;}
0 0
- hdu3555 Bomb 【数位dp+记忆化dfs】
- 【HDU3555】Bomb【数位DP】【记忆化搜索】
- 【数位DP】 hdu3555 Bomb
- 【hdu3555】【数位DP】Bomb
- 【数位DP】Bomb HDU3555
- hdu3555 Bomb 数位DP
- HDU3555:Bomb(数位DP)
- hdu3555 Bomb (数位DP)
- HDU3555 Bomb 数位DP
- Hdu3555 - Bomb - 数位dp
- hdu3555 Bomb 数位dp
- hdu3555 Bomb(数位DP)
- HDU3555 Bomb 数位DP
- HDU3555 Bomb 数位DP
- HDU3555 Bomb(数位DP)
- hdu3555 Bomb(数位dp)
- 【数位DP】HDU3555-Bomb
- hdu3555 Bomb --数位dp
- 开始写博客了...
- js数据类型判断和数组判断
- 编码规范 编写灵活、稳定、高质量的 HTML 和 CSS 代码的规范。
- 给VS2005 2008等添加代码对照线,对齐线
- Android DownloadManager源码笔记
- hdu3555 Bomb 【数位dp+记忆化dfs】
- 海盗分金问题
- 【转】R-CNN学习笔记4:Fast R-CNN
- JQuery(入门三)
- bjfu1069格式化数字
- Java常见的四种引用
- 破解 idea 2016
- PAT甲级练习题A1023. Have Fun with Numbers (20)
- 矩阵乘法 Matrix Power Series