HDU 3555 Bomb(数位dp)

题目链接:HDU 3555 Bomb

数位dp。

这个题有三种状态,0表示前一位不是4并且前几位没有49,1表示前一位是4并且前几位没有49,2表示前几位有49。

剩下的全写在注释上了。

#include <iostream>
#include <cstring>

using namespace std;

const int MAX_N = 20 + 5;
long long dp[MAX_N][3];
long long num[MAX_N];
long long n;
int T;

long long f(int pos, int st, bool limit)
{
    if(pos == -1)
        return st == 2;
    if(!limit && dp[pos][st] != -1)
        return dp[pos][st];
    long long ans = 0;
    int last = limit ? num[pos] : 9;
    for(int i = 0; i <= last; i++)
    {
        int temp = st;//开始没这么写,返回值一直是0。。。
        if(st == 1 && i == 9)//前一位是4,这一位是9
            temp = 2;
        else if(st == 1 && i != 4)//前一位是4,这一位不是4
            temp = 0;
        else if(i == 4 && st != 2)//这一位是4并且前边不包括49,即st != 2
            temp = 1;
        ans += f(pos - 1, temp, limit && i == last);
    }
    if(!limit)
        dp[pos][st] = ans;
    return ans;
}
long long cal(long long n)
{
    int pos = 0;
    while(n > 0)
    {
        num[pos] = n % 10;
        n /= 10;
        pos++;
    }
    return f(pos - 1, 0, 1);
}
int main()
{
    cin >> T;
    memset(dp, -1, sizeof(dp));
    while(T--)
    {
        cin >> n;
        cout << cal(n) << endl;
    }
    return 0;
}


你可能感兴趣的:(HDU 3555 Bomb(数位dp))