zoukankan      html  css  js  c++  java
  • 【BZOJ】1026 [SCOI2009]windy数

    算法】数位DP

    【题解】参考题解

    记忆化搜索挺好写的,而且比DP+递推快。

    大概思路是记录h(高度),pre(前一位数字),limit(限制)。

    从根往叶子走,limit=0时,扫0~9判断符合条件就递归。

    limit=1时,也就是当前位于n上,只能扫0~end-1,end就要limit=1来递归。

    过程中记录一下f数组防止复算。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int f[20][20],l,r,a[20];
    int dfs(int h,int pre,int limit)
    {
        if(h==-1)return 1;
        if(pre!=-1&&!limit&&f[h][pre]!=-1)return f[h][pre];
        int end=limit?a[h]:9;int ans=0;
        for(int i=0;i<=end;i++)
         {
             if(pre==-1&&i==0)ans+=dfs(h-1,-1,end==0?1:0);
              else
             if(abs(i-pre)>=2||pre==-1) 
             {
                 if(i==end&&limit)ans+=dfs(h-1,i,1);
                  else ans+=dfs(h-1,i,0);
             }
         }
        if(!limit)f[h][pre]=ans;
        return ans;
    }
    int solve(int x)
    {
        if(x==0)return 1;
        int n=0;
        while(x>0)a[n++]=x%10,x/=10;
        return dfs(n-1,-1,1);
    }
    int main()
    {
        scanf("%d%d",&l,&r);
        memset(f,-1,sizeof(f));
        printf("%d",solve(r)-solve(l-1));
        return 0;
    }
    View Code

    补一个递推,特别注意逐位确定的时候判断合法。

    #include<cstdio>
    #define ll long long
    int abs(int x){return x>=0?x:-x;}
    ll f[20][20];
    int A,B,a[20];
    int solve(int x){
        x++;
        int len;
        for(len=1;x;len++){
            a[len]=x%10;
            x/=10;
        }
        len--;
        ll ans=0;
        for(int i=len-1;i>=1;i--)for(int j=1;j<=9;j++)ans+=f[i][j];
        for(int i=len;i>=1;i--){
            for(int j=(i==len);j<a[i];j++)if(abs(j-a[i+1])>=2||i==len){
                ans+=f[i][j];
            }
            if(i!=len&&abs(a[i]-a[i+1])<2)break;
        }
        return ans;
    }
        
    int N;
    int main(){
        scanf("%d%d",&A,&B);N=10;
        for(int j=0;j<=9;j++)f[1][j]=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];
                }
            }
        }
        printf("%d",solve(B)-solve(A-1));
        return 0;
    }
    View Code
  • 相关阅读:
    vue 倒计时返回首页
    vue2借助animate.css实现路由动画效果
    CSS3实现文本垂直排列
    button在点击时出现边框
    vue项目中设置背景图片
    Python -处理PDF
    Python学习笔记(1)-列表
    转:Redis 的安装配置介绍
    转:windows xp下如何安装SQL server2000企业版
    转:CodeCube提供可共享、可运行的代码示例
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6708455.html
Copyright © 2011-2022 走看看