hdu 3555 Bomb(数位dp)
来源:互联网 发布:js正则判断数字长度 编辑:程序博客网 时间:2024/05/15 04:37
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <vector>#include <queue>#include <stack>#include <cassert>#include <algorithm>#include <cmath>#include <set>#include <list>#include <map>#include <limits>using namespace std;#define MIN(a, b) ((a) < (b) ? (a) : (b))#define MAX(a, b) ((a) > (b) ? (a) : (b))#define REP(i, s, t) for(int (i)=(s);(i)<=(t);++(i))#define UREP(i, s, t) for(int (i)=(s);(i)>=(t);--(i))#define REPOK(i, s, t, o) for(int (i)=(s);(i)<=(t) && (o);++(i))#define MAXN 19/***************BEGINHERE*****************/LL f[MAXN+1][10];LL a[MAXN+1];LL t;LL n;LL Count(LL x) { int cnt = 0; while(x) { a[cnt++] = x%10; x/=10; } LL ret = 0; a[cnt] = -1; UREP(i, cnt-1, 0) { REP(j, 0, a[i]-1) { if (a[i+1] == 4 && j == 9) continue; ret += f[i+1][j]; } if (a[i+1] == 4 && a[i] == 9) break; } return ret;}int main() { freopen("input.in", "r", stdin); cin >> t; REP(i, 1, 9) f[0][i] = 0; f[0][0] = 1; REP(k, 1, 19) REP(i, 0, 9) { f[k][i] = 0; REP(j, 0, 9) if (!(i == 4 && j == 9)) { f[k][i] += f[k-1][j]; } } while (t--) { cin >> n; cout << n-Count(n+1) + 1 << endl; } return 0;}
记忆化搜索:
注意保存状态的时候的维度问题,比如 dp(pos, pre, flag, limit) 的话
下面的代码是错的,比如140,会得到2的结果
原因是,在049的时候保存了状态 (0, 4, 0)
所以在14*的时候发现 (0,4,0) 这个状态已经是1,就直接返回。。
解决方法是,特判 limit=1 的状态 或者 增加维度
LL dp(int pos, int pre, int flag, int limit) { if (pos < 0) return flag; if (f[pos][pre][flag] == -1) { int last = limit ? d[pos] : 9; LL ret = 0; for (int i=0;i<=last;++i) { LL sav = ret; ret += dp(pos-1, i, flag || pre == 4 && i == 9, limit && i == last); if (ret > sav) { cout << "here: "; cout << pos << ' ' << pre << ' ' << flag << ' ' << limit << " now: " << i << endl; } } f[pos][pre][flag] = ret; } else if (f[pos][pre][flag]) {cout << "bug: ";cout << pos << ' ' << pre << ' ' << flag << ' ' << limit << endl;} return f[pos][pre][flag];}
正确的记忆化解法
LL f[22][10][2], d[22], n, len;LL dp(int pos, int pre, int flag, int limit) { if (pos < 0) return flag; // 特判 limit 的情况,防止重复计数 if (limit || f[pos][pre][flag] == -1) { int last = limit ? d[pos] : 9; LL ret = 0; for (int i=0;i<=last;++i) { LL sav = ret; ret += dp(pos-1, i, flag || pre == 4 && i == 9, limit && i == last); } f[pos][pre][flag] = ret; } return f[pos][pre][flag];}LL solve() { len = 0; while (n) {d[len++] = n%10;n /= 10;} memset(f, -1, sizeof(f)); return dp(len-1, 0, 0, 1);}
0 0
- HDU 3555 Bomb (数位DP)
- hdu 3555 - Bomb [数位dp]
- hdu 3555 Bomb【数位DP】
- HDU 3555 Bomb (数位DP)
- hdu 3555 Bomb 数位DP
- HDU 3555 Bomb (数位DP)
- hdu 3555 Bomb 数位dp
- [HDU 3555]Bomb[数位DP]
- HDU 3555 Bomb 数位DP
- hdu 3555 Bomb 数位dp
- HDU --3555--Bomb--数位DP
- hdu 3555 Bomb (数位DP)
- 【数位DP】【HDU 3555】Bomb
- hdu 3555 Bomb(数位DP)
- HDU 3555 Bomb(数位dp)
- 数位dp HDU 3555 Bomb
- HDU-3555 Bomb 数位DP
- HDU 3555 Bomb(数位DP)
- 3518流媒体服务器-h264资料-crtmpserver分析
- 利用JAVA+SWING+HTTPCLIENT+EXE4J 开发 海底捞 欢乐卡余额 批处理查询
- 黑马程序员——IO流
- 广东韶关2名重刑犯越狱 1人被击落1人逃脱
- 感谢好朋友推荐的一首好听的歌
- hdu 3555 Bomb(数位dp)
- ZooKeeper启动过程2:FastLeaderElection
- office ribbon风格修改功能区
- Maven2的配置文件settings.xml
- 猛将:一男挑7美女
- 文本复制、剪切、撤销
- 黑马程序员——异常机制3:自定义异常
- 每日学算法(一):插入排序
- 【恢复,1】 redo 日志恢复的各种情况