HDOJ 3555 Bomb (按位DP)

题目大意:求1到n中有多少个数含“49”

第一次接触按位DP,参考了别人的题解。

第一个代码运行速度快些(31ms),但状态的转移的分析比较麻烦,第二个代码要慢些(125ms),但code比较方便。

View Code
#include <stdio.h>
#include <string.h>
#define LEN 22
typedef __int64 LL;
char s[LEN];
LL dp[LEN][3][2];
int next(int cur,int in)
{
    if(cur==2 || cur==1&&in==9) return 2;
    return in==4;
}
LL DP(char s[],int len)
{
    memset(dp,0,sizeof(dp));
    dp[0][0][1]=1;
    for(int i=1;i<=len;i++)
    {
        dp[i][0][0]=9*dp[i-1][0][0]+8*dp[i-1][1][0];
        dp[i][1][0]=dp[i-1][0][0]+dp[i-1][1][0];
        dp[i][2][0]=10*dp[i-1][2][0]+dp[i-1][1][0];

        for(int j=0;j<s[i]-'0';j++)
        {
            dp[i][next(0,j)][0]+=dp[i-1][0][1];
            dp[i][next(1,j)][0]+=dp[i-1][1][1];
            dp[i][next(2,j)][0]+=dp[i-1][2][1];
        }

        dp[i][next(0,s[i]-'0')][1]+=dp[i-1][0][1];
        dp[i][next(1,s[i]-'0')][1]+=dp[i-1][1][1];
        dp[i][next(2,s[i]-'0')][1]+=dp[i-1][2][1];
    }
    return dp[len][2][0]+dp[len][2][1];
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s+1);
        printf("%I64d\n",DP(s,strlen(s+1)));
    }
    return 0;
}
View Code
#include <stdio.h>
#include <string.h>
#define LEN 22
typedef __int64 LL;
char s[LEN];
LL dp[LEN][3][2];
int nextstate(int cur,int in)
{
    if(cur==2 || cur==1&&in==9) return 2;
    return in==4;
}
int nextflag(int cur,int in,int max)
{
    if(cur==1 && in==max)   return 1;
    if(cur==1 && in>max)    return -1;
    return 0;
}
LL DP(char s[],int len)
{
    memset(dp,0,sizeof(dp));
    dp[0][0][1]=1;
    for(int i=1;i<=len;i++)
    {
        for(int state=0;state<3;state++)
        {
            for(int flag=0;flag<2;flag++)
            {
                for(int j=0;j<10;j++)
                {
                    if(nextflag(flag,j,s[i]-'0')==-1)   continue;
                    dp[i][nextstate(state,j)][nextflag(flag,j,s[i]-'0')]+=dp[i-1][state][flag];
                }
            }
        }
    }
    return dp[len][2][0]+dp[len][2][1];
}
int main()
{
    freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s+1);
        printf("%I64d\n",DP(s,strlen(s+1)));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/algorithms/p/2619186.html