zoukankan      html  css  js  c++  java
  • 几个基础数位DP(hdu 2089,hdu 3555,uestc 1307 windy 数)

    转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove

    做了几个非常基础的数位DP,很水。弱爆了,接下来要进行进阶训练了


    HDU 2089 不要62

    http://acm.hdu.edu.cn/showproblem.php?pid=2089

    不能出现4,或者相邻的62,这题可以暴力打表解决

    具体的在代码里都有解释

    #include<iostream>  
    #include<cstring>  
    #include<queue>  
    #include<cstdio>  
    #include<cmath>  
    #include<algorithm>  
    #define N 55  
    #define inf 1<<29  
    #define MOD 9973  
    #define LL long long  
    #define eps 1e-7  
    #define zero(a) fabs(a)<eps  
    #define equal(a,b) zero(a-b)  
    using namespace std;  
    int dp[10][3];  
    //dp[i][0],表示不存在不吉利数字  
    //dp[i][1],表示不存在不吉利数字,且最高位为2  
    //dp[i][2],表示存在不吉利数字  
    void Init(){  
        memset(dp,0,sizeof(dp));  
        dp[0][0]=1;  
        for(int i=1;i<=6;i++){  
            dp[i][0]=dp[i-1][0]*9-dp[i-1][1];  //在最高位加上除了4之外的9个数字,但是可能在2之前加了6  
            dp[i][1]=dp[i-1][0];    //就是在原先不含不吉利数字的最高位加2  
            dp[i][2]=dp[i-1][2]*10+dp[i-1][0]+dp[i-1][1];  //在已经有不吉利数字最高位加任意数字,或者在无吉利数字前加4,或者在2前面加4  
        }  
    }  
    int slove(int n){  
        int len=0,bit[10];  
        int tmp=n;  
        while(n){  
            bit[++len]=n%10;  
            n/=10;  
        }  
        bit[len+1]=0;  
        int ans=0;  
        bool flag=false;  
        for(int i=len;i;i--){  
            ans+=dp[i-1][2]*bit[i];    
            if(flag)   //高位已经出现4或者62,后面的就随意  
                ans+=dp[i-1][0]*bit[i];  
            if(!flag&&bit[i]>4)  //高位可能出现4的情况  
                ans+=dp[i-1][0];  
            if(!flag&&bit[i+1]==6&&bit[i]>2)  //高位是6,后面一位可能出现2,这步debug了很久  
                ans+=dp[i][1];  
            if(!flag&&bit[i]>6)  //高位可能出现6,要把后面最高位为2计入  
                ans+=dp[i-1][1];  
            if(bit[i]==4||(bit[i+1]==6&&bit[i]==2))  //高位已经出现4或者62  
                flag=true;  
        }  
        return tmp-ans;  
    }  
    int main(){  
        int l,r;  
        Init();  
        while(scanf("%d%d",&l,&r)!=EOF&&l+r)  
            printf("%d\n",slove(r+1)-slove(l));  
        return 0;  
    }  

    HDU 3555 BOMB

    http://acm.hdu.edu.cn/showproblem.php?pid=3555

    不能出现相邻的49,和上一题类似

    #include<iostream>  
    #include<cstring>  
    #include<queue>  
    #include<cstdio>  
    #include<cmath>  
    #include<algorithm>  
    #define N 55  
    #define inf 1<<29  
    #define MOD 9973  
    #define LL long long  
    #define eps 1e-7  
    #define zero(a) fabs(a)<eps  
    #define equal(a,b) zero(a-b)  
    using namespace std;  
    LL dp[21][3],n;   
    int len,bit[21];  
    //dp[i][0]表示长度为i,包括49的个数  
    //dp[i][1]表示长度为i,没有49但是开头为9的个数  
    //dp[i][2]表示长度为i,没有49  
    void Init(){  
        memset(dp,0,sizeof(dp));  
        dp[0][2]=1;  
        for(int i=1;i<20;i++){  
            dp[i][0]=(LL)dp[i-1][0]*10+dp[i-1][1];  
            dp[i][1]=dp[i-1][2];  
            dp[i][2]=(LL)dp[i-1][2]*10-dp[i-1][1];  
        }  
    }  
    int main(){  
        Init();  
        int t;  
        scanf("%d",&t);  
        while(t--){  
            scanf("%I64d",&n);  
            len=0;  
            n++;  
            while(n){  
                bit[++len]=n%10;  
                n/=10;  
            }  
            bit[len+1]=0;  
            LL ans=0;  
            bool flag=false;  
            for(int i=len;i;i--){  
                ans+=(LL)dp[i-1][0]*bit[i];  
                if(flag)  
                    ans+=(LL)dp[i-1][2]*bit[i];  
                if(!flag&&bit[i]>4)  
                    ans+=dp[i-1][1];  
                if(bit[i]==9&&bit[i+1]==4)  
                    flag=true;  
            }  
            printf("%I64d\n",ans);  
        }  
        return 0;  
    }  

    UESTC 1307 WINDY 数

    http://acm.uestc.edu.cn/problem.php?pid=1307

    要求相邻的数差大于等于2

    #include<iostream>  
    #include<cstring>  
    #include<queue>  
    #include<cstdio>  
    #include<cmath>  
    #include<algorithm>  
    #define N 100005  
    #define inf 1<<29  
    #define MOD 9973  
    #define LL long long  
    #define eps 1e-7  
    #define zero(a) fabs(a)<eps  
    #define equal(a,b) zero(a-b)  
    using namespace std;  
    int dp[15][10];  
    //dp[i][j]表示考虑i位的数中,最高为j的windy数  
    void Init(){  
        memset(dp,0,sizeof(dp));  
        for(int i=0;i<=9;i++)  
            dp[1][i]=1;  
        for(int i=2;i<=10;i++){  
            for(int j=0;j<10;j++){  
                for(int k=0;k<10;k++)  
                    if(abs(j-k)>=2)  
                        dp[i][j]+=dp[i-1][k];  
            }  
        }  
    }  
    int slove(int n){  
        int len=0,bit[15];  
        while(n){  
            bit[++len]=n%10;  
            n/=10;  
        }  
        bit[len+1]=0;  
        int ans=0;  
        //先把长度为1至len-1计入  
        for(int i=1;i<len;i++)  
            for(int j=1;j<10;j++)  
                ans+=dp[i][j];  
        //确定最高位  
        for(int j=1;j<bit[len];j++)  
            ans+=dp[len][j];  
        for(int i=len-1;i;i--){  
            for(int j=0;j<bit[i];j++)  
                if(abs(j-bit[i+1])>=2)  
                    ans+=dp[i][j];  
            //如果高位已经出现非法,直接退出  
            if(abs(bit[i]-bit[i+1])<2)  
                break;  
        }  
        return ans;  
    }  
    int main(){  
        Init();  
        int l,r;  
        while(scanf("%d%d",&l,&r)!=EOF)  
            printf("%d\n",slove(r+1)-slove(l));  
        return 0;  
    }  



  • 相关阅读:
    random模块的讲解
    函数的商城代码练习
    python文件作业
    函数的学习
    三元表达式和列表生成式
    jQuery 遍历方法
    CSS font属性综合写法
    JQuery 添加节点
    Bootstrap 响应式中的兼容
    jQuery 中的attr和prop的区别
  • 原文地址:https://www.cnblogs.com/java20130726/p/3218214.html
Copyright © 2011-2022 走看看