zoukankan      html  css  js  c++  java
  • hdu 2089 入手数位dp问题

    数位dp解决的问题是指求在一段数的区间里面 满足条件的数的个数

    核心为两点 

    http://wenku.baidu.com/link?url=tpfIYzhx_MzevpIM58UZ66pr-87MCFPKTMKFdGDi5jUqyO9ckti0mY6diSz2PZEL_ZBhd2zIbhus1mnzDiAO1B5K2Vu38YDsqjmOvYKFT6q

    我自己总结下吧

    第一 是dp的状态转移方程 

    dp[i][j] 表示的是以j开头的i位数 满足条件的个数为多少 

    既然是要记录满足条件的个 那么 dp[i][j]=sum(dp[i-1][0~9]) 这个不难理解 

    for(int i=1;i<=7;i++)
            {
                for(int j=0;j<=9;j++)
                {
                    for(int k=0;k<=9;k++)
                    {
                        if(j!=4&&!(j==6&&k==2)) dp[i][j]+=dp[i-1][k];
                    }
                }
            }

    然后就是solve函数问题 solve(i)这个函数的作用是求出【0,i)区间满足条件的数的个数

    大致的思想 是从高位开始 逐一枚举比该为数小的数 在满足的条件的情况下 统计和 每次枚举完

    举完一位以后 由于是列举比n小的数 所以 每一位枚举结束后 就需要将这个位定下来 

    花了不少时间入门。。继续干!

    #include<cstdio>
    #include<iostream>
    #include<string.h>
    using namespace std;
    int dp[11][11]; 
    int solve(int n)
    {
        int dig[10],len=0;
        memset(dig,0,sizeof(dig));
        while(n>0)
        {
            dig[++len]=n%10;
            n=n/10;
        }
        dig[len+1]=0;
        int ans=0;
        for(int i=len;i;i--)//这里的思想 从最高位开始枚举 枚举完一位以后 由于是列举比n小的数 所以 每一位枚举结束后 就需要将这个位定下来 
        {
            for(int j=0;j<dig[i];j++)
            {
                if(j!=4&&!(dig[i+1]==6&&j==2))//判断此时的枚举是否合法 
                ans+=dp[i][j];    
            }
            if(dig[i]==4||(dig[i+1]==6&&dig[i]==2)) break;//之前位置定好了 如果出现了不满足条件的情况 后面继续下去就没有什么意思了 
        }
        return ans;
    }
    int main()
    {
        int n,m;
        while(cin>>n>>m)
        {
            if(m+n==0) break;
            memset(dp,0,sizeof(dp));
            dp[0][0]=1;
            for(int i=1;i<=7;i++)
            {
                for(int j=0;j<=9;j++)
                {
                    for(int k=0;k<=9;k++)
                    {
                        if(j!=4&&!(j==6&&k==2)) dp[i][j]+=dp[i-1][k];
                    }
                }
            }
            cout<<solve(m+1)-solve(n)<<endl;// 这里要不要加1是要考虑区间的开闭情况 
        }
        return 0;
    }
  • 相关阅读:
    如何测量字符串的高度宽度 and 精确取得字符串的高度宽度
    ListBox删除多项选择项
    Configuring TCP/IP settings by WMI. 用WMI对象访问.设置IP配置
    .Net Jpeg编码器bug
    foreach与for的性能比较
    Linq 处理 List数据
    JS中的拖动之—— ondragstart,ondrag,ondragend , ondragenter , ondragover , ondragleave, ondrop 的区别
    url参数中有+、空格、=、%、&、#等特殊符号的问题解决
    判断一个字符串是否在另一个字符串中
    <span>居中
  • 原文地址:https://www.cnblogs.com/z1141000271/p/5740020.html
Copyright © 2011-2022 走看看