您的位置:首页 > 其它

【算法笔记】数位dp小结

2015-03-14 16:47 183 查看

资料链接:

入门ppt

link1:记忆化方式

link2

link3

论文1

论文2

//=====================//

记忆化的数位dp:

通常而言,有四个参数必须 dp( pos, flag, limit )

pos表示当前正在枚举的数位。

flag标志已经枚举的前缀是否某种性质(前面的数位和,是否含有某个数,前一个枚举的数等等。。),当然flag可以有多个。

limit表示当前是否为上限,有时还会记录是否有前导0。

相较而言,记忆化搜索更容易编写,需要维护的细节更少。

假设要对数位中没有5的数计数。

int digit[Maxn], dp[Maxn][flag];

// 在程序最开始初始化一次即可(假设有多个区间需要询问),想想为什么
void init() {
memset(dp, -1, sizeof(dp));
}

// flag 是否没有5
int go (int pos, int limit, int flag) {
if (pos < 0) {
return flag == 1;
}

if (limit || dp[pos][flag] == -1) {
int tmp = 0;
int last = limit ? digit[pos] : 9;
for (int i=0;i<=last;++i)
tmp += go (pos - 1, limit && (i == last), flag && (i != 5));
if (limit) return tmp; // 上界要单独计算,不能存状态
dp[pos][flag] = tmp;
}
return dp[pos][flag];
}

// count [1, x]
int Count(int x) {
int len = 0;
while (x) {
digit[len ++] = x % 10; x /= 10;
}
return go (0,
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: