AcWing1083 Windy数(数位dp)

这题要求不含前导零,所以我们要对有前导0的数,进行枚举一遍

前两题之所以可以用含前导零的来直接做,是因为不影响答案,比如度的数量,第一位选0没有问题

又比如不降数问题,即使有前导0,也不影响答案,所以可以不处理

但是对于windy数,会影响答案,比如一个数0135,按道理是135是符合答案的,但是加上前导0就不符合了,所以这题必须处理前导0

#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 35;

int f[N][10];

void init()
{
    for (int i = 0; i <= 9; i ++ ) f[1][i] = 1;

    for (int i = 2; i < N; i ++ )
        for (int j = 0; j <= 9; j ++ )
            for (int k = 0; k <= 9; k ++ )
                if (abs(j - k) >= 2)
                    f[i][j] += f[i - 1][k];
}

int dp(int n)
{
    if (!n) return 0;

    vector<int> nums;
    while (n) nums.push_back(n % 10), n /= 10;

    int res = 0;
    int last = -2;
    for (int i = nums.size() - 1; i >= 0; i -- )
    {
        int x = nums[i];
        if (x)
        {
            for (int j = 1; j < x; j ++ )
                if (abs(last - j) >= 2)
                    res += f[i + 1][j];
            if (i != nums.size() - 1)
                if (abs(last - 0) >= 2)
                    res += f[i + 1][0];
        }

        if (abs(last - x) < 2) break;
        last = x;

        if (!i) res ++ ;
    }

    for (int i = 1; i < nums.size(); i ++ )
        for (int j = 1; j <= 9; j ++ )
            res += f[i][j];

    return res;
}

int main()
{
    init();

    int l, r;
    cin >> l >> r;

    cout << dp(r) - dp(l - 1) << endl;

    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/ctyakwf/p/12649960.html