数位DP入门 + 待补上最后一题

来源:互联网 发布:什么软件可以套花呗 编辑:程序博客网 时间:2024/06/13 22:54

学了一下数位DP后才会做范老师的题目。

HDU2689不要62
模板题 , dfs写法,大概理解数位dp的思想以及简洁的写法。limit:是否受限,zero:是否一直在前导零。数位dp的精髓在于记忆化搜索。

#include<bits/stdc++.h>using namespace std;const int N = 10000;int dp[N][2] , l , r , ans , a[N] , cnt;int dfs(int pos  ,int six , int limit) {    if(!pos) return 1;    if(!limit && dp[pos][six] != -1) return dp[pos][six];    int up = limit ? a[pos] : 9;    int res = 0;    for(int i = 0;i <= up;i ++) {        if(i == 4) continue;        if(six && i == 2) continue;        res += dfs(pos - 1, i == 6, a[pos] == i && limit);    }    if(!limit) dp[pos][six] = res;    return res;}int solve(int x) {    cnt = 0;     while(x) {        a[++ cnt] = x % 10;        x /= 10;    }    return dfs(cnt , 0 , 1);}int main() {    memset(dp,-1,sizeof(dp));    while(scanf("%d%d",&l,&r) == 2 && l + r) {        printf("%d\n",solve(r) - solve(l - 1));    }}

BZOJ1026 Windy数
考虑前导零和limit细节不多,模版思路跟着走即可。

#include<bits/stdc++.h>using namespace std;const  int N = 35;int dp[N][15] , n , m , l , r , cnt , a[N];int dfs(int pos ,int limit , int lead, int sta) {    if(!pos) return 1;    if(!limit && !lead && dp[pos][sta] != -1) return dp[pos][sta];    int up = limit ? a[pos] : 9;    int res = 0;    for(int i = 0;i <= up;i ++) {        if(abs(i - sta) <= 1) continue;        res += dfs(pos - 1 , a[pos] == i && limit , lead && (!i),(lead && (!i)) ? -100 : i);    }    if(!limit && !lead) dp[pos][sta] = res;    return res; }  int solve(int x) {    cnt = 0;    while(x) {        a[++ cnt] = x % 10;        x /= 10;    }    return dfs(cnt , 1 , 1 , -100);}int main() {    memset(dp,-1,sizeof(dp));    scanf("%d%d",&l,&r);    printf("%d\n",solve(r) - solve(l - 1));}

最后就是一道比较神的数位DP,范老师的T3

原创粉丝点击