fzu 2109 Mountain Number 数位DP 记忆化搜索

做法:按位暴力DFS吧...

这里很明显没有考虑当前数字是否是首位,其实不需要啊,因为这种情况发生的时候肯定是那种比边界数少一位的数字。也就是说如果求1234 那么这里要考虑的是 0 ---999的

数字中的mountain, 没有考虑首位的后果是moutain的形态不同,可是很容易证明,规定位数的数字只有两种moutain,而这种两种moutain在 0---999中的个数相同。

#include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
const int LMT=11;
using namespace std;
LL dp[LMT][LMT][LMT];
int sec[LMT];
LL dfs(int pre,int pos,int len,bool tag)
{
    if(dp[pre][pos][len]!=-1&&(!tag||pos==len))return dp[pre][pos][len];
    LL res=0;
    int end=tag?sec[pos]:9;
    if(pos&1)
    {
        for(int j=end;j>=pre;j--)
        res+=dfs(j,pos+1,len,tag&&j==end);
    }
    else
    {
        for(int j=min(end,pre);j>=0;j--)
        res+=dfs(j,pos+1,len,tag&&j==end);
    }
    if(!tag)dp[pre][pos][len]=res;
    return res;
}
int work(LL x)
{
    int num[LMT],res=0;
    do
    {
        num[res]=x%10;
        res++;
    }
    while(x/=10);
    for(int i=0,j=res-1;j>=0;j--,i++)
    sec[i]=num[j];
    return res;
}
int main(void)
{
    int T;
    scanf("%d",&T);
    memset(dp,-1,sizeof(dp));
    for(int i=0;i<LMT;i++)
     for(int j=0;j<LMT;j++)
     dp[i][j][j]=1;
    while(T--)
    {
        LL a,b,x,y;
        scanf("%I64d%I64d",&a,&b);
        x=dfs(9,0,work(a-1),1);
        y=dfs(9,0,work(b),1);
        printf("%I64d\n",y-x);
    }
    return 0;
}


你可能感兴趣的:(fzu 2109 Mountain Number 数位DP 记忆化搜索)