数位DP总结

数位DP=区间求符合条件的数的个数的算法=数很大,无法直接暴力的算法≈让人苦恼愤怒,依然D不出来的勾魂算法

数位DP的两种写法:

1、递推

 结构:

init()函数,根据递推数位的公式求得的满足某长度的符合数的个数

cal()函数,假设要计算的数字为n,数位长度为len。1到len-1长度累加,len长度的拿出来一个位置一个位置遍历判定再累加。

输出cal(right+1)-cal(left),right为区间最右,left为区间最左

 

模板:

int f[35][35],digit[35];
void Init()
{
    int i,j;
    /*递推关系式,请忽略
    f[0][0]=1;
    for(i=1; i<32; ++i)
    {
        f[i][0]=f[i-1][0];
        for(j=1; j<=i; ++j)
            f[i][j]=f[i-1][j]+f[i-1][j-1]; 
    }
    */
}

int Cal(int x,int k,int b) 
{
    int tot=0,len=0,ans=0,i;
    while(x) //初始化数位
    {
        digit[++len]=x%b;
        x/=b;
    }
    for(i=len;i&&tot<=k;--i) //分长度累加
    {
      /*判断累加,请忽略
      if(digit[i]>1)  
      {
          ans+=f[i][k-tot];break;
      }
      if(digit[i]==1) 
      {
          ans+=f[i-1][k-tot];
          tot++;
      }
      */
    }
    return ans;
}
输出Cal(right+1)-Cal(left)

 

2、递归(记忆化搜索,据说记忆化搜索最优)

个人觉得记忆化搜索更简单,因为它的结构简单。dp数组d的是pos前面数组的状态。

结构:

dfs()函数,记忆化搜索符合条件的数的个数。记忆化搜索的参数无非是表示上一状态或者是下一状态的。

cal()函数,初始化数位,调用dfs函数。

输出cal(right)-cal(left-1)

 

模板:

int dfs(int pos , int pre , int have , bool doing) //doing为边界,pos为计算到当前第几位
{
    if(pos == -1)
        return have == 2 && pre == 0;

    if(!doing && dp[pos][pre][have] != -1) //若不是统计边界位,则直接返回记忆下的数
        return dp[pos][pre][have];

    int ans = 0;
    int end = doing ? digit[pos] : 9; 
    for(int i = 0 ; i <= end ; i ++)
    {
       /*初始化下一层dfs的参数,请忽略 
        int npre = (pre*10 + i) % 13; 
        int nhave = have;
        if(have == 0 && i == 1)
            nhave = 1;
        else if(have == 1 && i != 1)
            nhave = 0;
        if(have == 1 && i == 3)
            nhave = 2;
        */
        ans += dfs(pos-1 , npre , nhave , doing && i == end ); //doing在i==end的时候会是1
    }

    if(!doing)
        dp[pos][pre][have] = ans;
    return ans;
}


int cal(int x)
{
    int pos = 0;
    while(x)
    {
        digit[pos++] = x % 10;
        x /= 10;
    }
    return dfs(pos - 1 , 0 , 0 , 1);
}
输出Cal(right)-Cal(left-1)

 

posted @ 2013-04-11 20:51  小仪在努力~  阅读(378)  评论(0)    收藏  举报