zoukankan      html  css  js  c++  java
  • SCOI2009windy数-数位DP

    SCOI2009windy数

    题目传送

    sol:

    一道数位DP的基础题。然而还是几次没想清。

    这种求区间l,r的一般都用记忆化搜索的方法实现。

    如果不熟悉记搜实现的数位DP建议参考Here

    (getans(1,r)-getans(1,l-1))即为答案。

    考虑需要记录的变量:

    (pos)表示从高往低填到了第pos位,(now)表示上一位填的是(now)(lim)用于最高位限制,(lead)用于前导0判断。

    一般而言后面两个变量都是很套路很板子的列出。

    然后套上模板,注意当前位枚举的数的范围即可(受now和lim的影响)。

    另外为了方便,可以把(now)的值赋值为-2,用于填前导0。

    code:

    #include<cmath>
    #include<string>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define RG register
    #define IL inline
    #define LL long long
    #define DB double
    using namespace std;
    
    IL int gi() {
       RG int x=0,w=0; char ch=getchar();
       while (ch<'0'||ch>'9') {if (ch=='-') w=1;ch=getchar();}
       while (ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
       return w?-x:x;
    }
    
    int len,a[13],f[13][13];
    
    int dfs(int pos,int now,int lim,int lead) {
    	if(pos>len) return 1;
    	if(!lim&&f[pos][now]!=-1) return f[pos][now];
     	RG int i,ans=0,up=lim?a[len-pos+1]:9;
    	for(i=0;i<=up;++i) {
    		if(abs(i-now)<2) continue;
    		if(lead&i==0) ans+=dfs(pos+1,-2,lim&&i==up,1);
    		else ans+=dfs(pos+1,i,lim&&i==up,0);
    	}
    	return (!lim&&!lead)?f[pos][now]=ans:ans;
    }
    
    IL int getans(int x) {
    	for(len=0;x;x/=10) a[++len]=x%10;
    	memset(f,-1,sizeof(f));
    	return dfs(1,-2,1,1);
    }
    
    int main()
    {
    	RG int l=gi(),r=gi();
    	printf("%d
    ",getans(r)-getans(l-1));
        return 0;
    }
    
  • 相关阅读:
    【APUE】Chapter15 Interprocess Communication
    【APUE】Chapter14 Advanced I/O
    【APUE】Chapter5 Standard I/O Library
    【APUE】Chapter4 File and Directories
    【APUE】Chapter3 File I/O
    【APUE】Chapter1 UNIX System Overview
    【APUE】Chapter13 Daemon Processes
    【APUE】Chapter10 Signals
    Hive之数据类型
    Hive之内置函数
  • 原文地址:https://www.cnblogs.com/Bhllx/p/11017650.html
Copyright © 2011-2022 走看看