zoukankan      html  css  js  c++  java
  • [SCOI2009] Windy数

    所以今天的主题就是数位DP吧

    不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。在A和B之间,包括A和B,总共有多少个windy数?

    (f[i][j]) 从低到高 (i) 位,第(i)位是(j)的方案数

    初态:(f[1][i] = 1)

    转移:(f[i][j]=f[i-1][k]), 需要满足若干约束条件

    如何统计答案?

    对于位数比 (n) 小的,直接统计即可

    对于位数相同的,枚举哪一位开始比 (n) 小,这样更高的位就确定了,更低的位只需要暴力选择即可

    #include <bits/stdc++.h>
    using namespace std;
    
    int f[15][15];
    const int m = 10;
    int t[15];
    
    int calc(int n) {
        if(n==0) return 0;
        int ans = 0;
        int x = n, y = 0;
        while(x) {
            t[++y] = x % 10;
            x /= 10;
        }
        int len = y;
        for(int i=1;i<len;i++) {
            for(int j=1;j<=9;j++)
                ans += f[i][j];
        }
        for(int i=len;i>=0;--i) {
            if(i==0) {++ans; break;}
            if(i<len-1 && abs(t[i+1]-t[i+2])<2) break;
            for(int j=(i==len?1:0);j<=9;j++) {
                if(j < t[i] && (i==len || abs(t[i+1]-j)>=2)) {
                    if(i==1) ++ans;
                    else for(int k=0;k<=9;k++) {
                        if(abs(k-j)>=2) {
                            ans += f[i-1][k];
                        }
                    }
                }
            }
        }
        return ans;
    }
    
    int main() {
        for(int i=0;i<=9;i++) f[1][i]=1;
        for(int i=2;i<=m;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 a,b;
        cin>>a>>b;
        cout<<calc(b) - calc(a-1)<<endl;
    }
    
  • 相关阅读:
    133
    132
    131
    130
    129
    128
    2019.10.16考试解题报告
    2019.10.15考试解题报告
    洛谷 P1352 没有上司的舞会
    2019.10.13考试解题报告
  • 原文地址:https://www.cnblogs.com/mollnn/p/12259558.html
Copyright © 2011-2022 走看看