zoukankan      html  css  js  c++  java
  • hdu 5787 K-wolf Number 数位dp

    数位DP 神模板 详解

    为了方便自己参看,我把代码复制过来吧

    //    pos    = 当前处理的位置(一般从高位到低位)
    //    pre    = 上一个位的数字(更高的那一位)
    //    status = 要达到的状态,如果为1则可以认为找到了答案,到时候用来返回,
    //            给计数器+1。
    //    limit  = 是否受限,也即当前处理这位能否随便取值。如567,当前处理6这位,
    //            如果前面取的是4,则当前这位可以取0-9。如果前面取的5,那么当前
    //            这位就不能随便取,不然会超出这个数的范围,所以如果前面取5的
    //            话此时的limit=1,也就是说当前只可以取0-6。
    //
    //    用DP数组保存这三个状态是因为往后转移的时候会遇到很多重复的情况。
    int    dfs(int pos,int pre,int status,int limit)
    {
        //已结搜到尽头,返回"是否找到了答案"这个状态。
        if(pos < 1)
            return    status;
    
        //DP里保存的是完整的,也即不受限的答案,所以如果满足的话,可以直接返回。
        if(!limit && DP[pos][pre][status] != -1)
            return    DP[pos][pre][status];
    
        int    end = limit ? DIG[pos] : 9;
        int    ret = 0;
        
        //往下搜的状态表示的很巧妙,status用||是因为如果前面找到了答案那么后面
        //还有没有答案都无所谓了。而limti用&&是因为只有前面受限、当前受限才能
        //推出下一步也受限,比如567,如果是46X的情况,虽然6已经到尽头,但是后面的
        //个位仍然可以随便取,因为百位没受限,所以如果个位要受限,那么前面必须是56。
        //
        //这里用"不要49"一题来做例子。
        for(int i = 0;i <= end;i ++)
            ret += dfs(pos - 1,i,status || (pre == 4 && i == 9),limit && (i == end));
    
        //DP里保存完整的、取到尽头的数据
        if(!limit)
            DP[pos][pre][status] = ret;
    
        return    ret;
    }

    传送门 hdu 5787 K-wolf Number

    吐槽:我以前是写过数位DP的,但是也就停留在表面上的理解,所以虽然我一看到题目就知道算法,但是,诶,没弄出来。。。感觉自己好渣!!!

    题意:给你一个区间,让你找满足任意k个数位内都没有相同的数字的个数

    思路:这题思路比较一致,dp[pos][a][b][c][d] pos表示当前位,a,b,c,d分别表示表示前4,3,2,1位。这里要考虑前导0的情况,d=10的时候表示前一位为0.所以当(d==10 && i==0)时表示当前的这位为0并且前四位都为0.所以向下dfs的话 ans+=dfs(temp-1,a,b,c,d,limit&&(i==ed));

    /**************************************************************
        Problem:hdu 5787 K-wolf Number
        User: youmi
        Language: C++
        Result: Accepted
        Time:265MS
        Memory:3872K
    ****************************************************************/
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    //#include<bits/stdc++.h>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <stack>
    #include <set>
    #include <sstream>
    #include <cmath>
    #include <queue>
    #include <deque>
    #include <string>
    #include <vector>
    #define zeros(a) memset(a,0,sizeof(a))
    #define ones(a) memset(a,-1,sizeof(a))
    #define sc(a) scanf("%d",&a)
    #define sc2(a,b) scanf("%d%d",&a,&b)
    #define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scs(a) scanf("%s",a)
    #define sclld(a) scanf("%I64d",&a)
    #define pt(a) printf("%d
    ",a)
    #define ptlld(a) printf("%I64d
    ",a)
    #define rep(i,from,to) for(int i=from;i<=to;i++)
    #define irep(i,to,from) for(int i=to;i>=from;i--)
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define lson (step<<1)
    #define rson (lson+1)
    #define eps 1e-6
    #define oo 0x3fffffff
    #define TEST cout<<"*************************"<<endl
    const double pi=4*atan(1.0);
    
    using namespace std;
    typedef long long ll;
    template <class T> inline void read(T &n)
    {
        char c; int flag = 1;
        for (c = getchar(); !(c >= '0' && c <= '9' || c == '-'); c = getchar()); if (c == '-') flag = -1, n = 0; else n = c - '0';
        for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) n = n * 10 + c - '0'; n *= flag;
    }
    int Pow(int base, ll n, int mo)
    {
        if (n == 0) return 1;
        if (n == 1) return base % mo;
        int tmp = Pow(base, n >> 1, mo);
        tmp = (ll)tmp * tmp % mo;
        if (n & 1) tmp = (ll)tmp * base % mo;
        return tmp;
    }
    //***************************
    
    ll k;
    ll dp[20][11][11][11][11];
    int dt[20];
    int tt;
    bool check(int temp,int a,int b,int c,int d)
    {
        if(k==2)
        {
            if(temp==d)
                return true;
        }
        else if(k==3)
        {
            if(temp==d||temp==c)
                return true;
        }
        else if(k==4)
        {
            if(temp==d||temp==c||temp==b)
                return true;
        }
        else if(k==5)
        {
            if(temp==d||temp==c||temp==b||temp==a)
                return true;
        }
        return false;
    }
    ll dfs(int temp,int a,int b,int c,int d,int limit)
    {
        if(temp<0)
            return 1ll;
        ll& now=dp[temp][a][b][c][d];
        if(!limit&&now)
            return now;
        ll ans=0;
        int ed=limit?dt[temp]:9;
        for(int i=0;i<=ed;i++)
        {
            if(check(i,a,b,c,d))
                continue;
            if(i==0&&d==10)
                ans+=dfs(temp-1,a,b,c,d,limit&&(i==ed));
            else
                ans+=dfs(temp-1,b,c,d,i,limit&&(i==ed));
    
        }
        if(!limit)
            now=ans;
        return ans;
    }
    ll sovle(ll n)
    {
        tt=0;
        while(n)
        {
            dt[tt++]=n%10;
            n/=10;
        }
        zeros(dp);
        return dfs(tt-1,10,10,10,10,1);
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
        #endif
        ll l,r;
        while(~scanf("%I64d%I64d%I64d",&l,&r,&k))
        {
            printf("%I64d
    ",sovle(r)-sovle(l-1));
        }
    }
    View Code
    不为失败找借口,只为成功找方法
  • 相关阅读:
    Vue路由1
    vue中的若干需要注意的点
    vue-使用ref属性获取和操作dom元素
    Vue子父组件间的传值【非常重要的一个知识点】
    Vue组件切换-以登录注册为例【加动画效果】
    Vue中的组件
    Vue动画
    MINIUI grid学习笔记
    (转) 【oracle调优】优化全表扫---cache整张表或索引
    (转) Delete/Truncate删除,释放表空间、降低高水位线、resize释放磁盘空间相关优化
  • 原文地址:https://www.cnblogs.com/youmi/p/5734892.html
Copyright © 2011-2022 走看看