zoukankan      html  css  js  c++  java
  • 一本通1587: 【例 3】Windy 数

    一本通1587: 【例 3】Windy 数

    原题链接

    数位dp裸题

    这道题对于前导0加个特判就好

    如果前面是前导0,那么搜索时把pre赋值成-2(当然<-2的数都可以)

    注意:这样处理之后dp数组就不能定义为dp[pos][pre][flag][lim](不懂的话见代码注释)

    因为pre哪里可能会是负数,所以只能有前两维,记忆化赋值的时候加特判,判断前面不是前导0,再赋值

    不多说了,直接看代码吧(有注释)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define ll long long
    
    using namespace std;
    
    ll l, r, len;
    ll num[20], dp[15][15];		//dp[pos][pre]:处理到第i位,上一位为j,且当前位可以取0~9,不是全部都为0时的方案数
    							//注意:这里不能dp[pos][pre][flag][lim](原因见下)
    
    ll dfs(ll pos, ll pre, ll flag, ll lim){	//pos:处理到第几位,pre:上一位是多少,flag:前面是否为前导0,lim:是否有上限
    	if(pos == len + 1) return 1;
    	if(!lim && dp[pos][pre] != -1) return dp[pos][pre];		//记忆化,这里只记忆了没有上限情况下的方案数
    	ll res = lim ? num[len - pos + 1] : 9;	//找上限,注意这里是倒着存的数,所以num[len-pos+1]
    	ll ans = 0;
    	for(ll i = 0; i <= res; i++){
    		if(abs(i - pre) < 2) continue;		//相差<2则continue
    		if(flag && !i) ans += dfs(pos + 1, -2, 1, lim && (i == res));	//如果前面为前导0,pre赋值成-2
    		else ans += dfs(pos + 1, i, 0, lim && (i == res));				//不是前导0的话正常dfs
    	}
    	if(!flag && !lim) dp[pos][pre] = ans;		//特判,前面不是前导0,且没有上限,记忆化
    	return ans;
    }
    
    ll solve(ll x){
    	len = 0;
    	while(x){
    		num[++len] = x % 10;
    		x /= 10;
    	}
    	memset(dp, -1, sizeof(dp));
    	return dfs(1, -2, 1, 1);
    }
    
    signed main(){
    	scanf("%lld%lld", &l, &r);
    	printf("%lld
    ", solve(r) - solve(l - 1));
    	return 0;
    }
    

    完结撒花~

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15102600.html

  • 相关阅读:
    IntelliJ idea 2021.3 安装使用及激活
    高项-信息系统基础-UML图
    软考高项(信息系统项目管理师)介绍
    Android Studio中的Gradle面板没有Task任务列表如何找回?
    ubuntu 安装nodejs,npm,
    解决video.js video-player不能自动播放问题
    vuex开启namespaced
    axios提交body raw格式
    vue配置服务代理
    PIDFile没有配置导致将mongodb配置成服务时启动失败
  • 原文地址:https://www.cnblogs.com/xixike/p/15102600.html
Copyright © 2011-2022 走看看