码迷,mamicode.com
首页 > 其他好文 > 详细

SCUT - 249 - Hello World - 数位dp

时间:2019-02-19 23:34:03      阅读:355      评论:0      收藏:0      [点我收藏+]

标签:\n   连续   开始   判断   ems   模板题   cas   数加   lin   

https://scut.online/p/249

数位dp的模板题?

需要特殊判断0,这个很不优雅,因为0-1=-1是个很奇葩的东西?

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int a[20];
ll dp[20][11][3];//不同题目状态不同
ll dfs(int pos,int eleven,int cnt6,bool lead/*前导零*/,bool limit/*数位上界变量*/)//不是每个题都要判断前导零
{
    //递归边界,最低位是0,那么pos==-1说明这个数枚举完了
    if(pos==-1)
        return 1;/*这里返回1,表示枚举的这个数是合法的,那么这里就需要在枚举时必须每一位都要满足题目条件,也就是说当前枚举到pos位,一定要保证前面已经枚举的数位是合法的。 */
    //第二个就是记忆化(在此前可能不同题目还能有一些剪枝)
    if(!limit && !lead && dp[pos][eleven][cnt6]!=-1)
        return dp[pos][eleven][cnt6];
    /*常规写法都是在没有限制的条件记忆化,这里与下面记录状态对应*/
    int up=limit?a[pos]:9;//根据limit判断枚举的上界up;这个的例子前面用213讲过了
    ll ans=0;
    //开始计数
    for(int i=0;i<=up;i++)//枚举,然后把不同情况的个数加到ans就可以了
    {
        int new_eleven=(eleven*10+i)%11;
        int new_cnt6=0;
        if(i==6)
            new_cnt6=cnt6+1;

        if(pos==0&&new_eleven==0)
            continue;
        if(new_cnt6>=3){
            continue;
        }

        ans+=dfs(pos-1,new_eleven,new_cnt6,lead && i==0,limit && i==a[pos]);//最后两个变量传参都是这样写的
        /*这里还算比较灵活,不过做几个题就觉得这里也是套路了
        大概就是说,我当前数位枚举的数是i,然后根据题目的约束条件分类讨论
        去计算不同情况下的个数,还有要根据state变量来保证i的合法性,比如题目
        要求数位上不能有62连续出现,那么就是state就是要保存前一位pre,然后分类,
        前一位如果是6那么这意味就不能是2,这里一定要保存枚举的这个数是合法*/
    }
    //计算完,记录状态
    if(!limit && !lead) dp[pos][eleven][cnt6]=ans;
    /*这里对应上面的记忆化,在一定条件下时记录,保证一致性,当然如果约束条件不需要考虑lead,这里就是lead就完全不用考虑了*/
    return ans;
}

ll solve(ll x)
{
    //特殊处理0
    if(x==0)
        return 0;

    int pos=0;
    while(x)//把数位分解
    {
        a[pos++]=x%10;//编号为[0,pos),注意数位边界
        x/=10;
    }

    return dfs(pos-1/*从最高位开始枚举*/,0,0,true,true);//刚开始最高位都是有限制并且有前导零的,显然比最高位还要高的一位视为0嘛
}

int main()
{
    memset(dp,-1,sizeof(dp));
    //初始化为-1

    ll le,ri;
    int cntcase=1;
    while(~scanf("%lld%lld",&le,&ri))
    {
        printf("Case #%d: %lld\n",cntcase++,solve(ri)-solve(le-1));
    }
}

 

SCUT - 249 - Hello World - 数位dp

标签:\n   连续   开始   判断   ems   模板题   cas   数加   lin   

原文地址:https://www.cnblogs.com/Yinku/p/10404043.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!