zoukankan      html  css  js  c++  java
  • 数位dp(模板&&以hdu2092为例)

    数位一般来说是求在一段范围内的满足某些条的数,假如说在[ri,le]的条件下满足一定条件的数的话,那么我们就可以采用差分的方法:

    就是count = solve(le) - solve(ri-1);或者count = solve(le) - solve(ri) + check(ri);

     即就是满足[0,le]的数 -满足 [0,ri-1]的数;

    数位dp通俗的讲就是按位上的暴力搜索然后求得的答案,我们需要从高位到低位这样搜索下去假如说我们要求满足[0,123456789]之间

    某个条件的数那么我们需要先从最高位开始搜索即(1)所在的位置也就是在这个例子中的第9位在这个位置上我们可以搜索的数有(0,1)

    然后我们再搜索第8位,第7位....一直到第1位,但是同时我们有不能超过所给的数字范围,所以我们在每次搜索的时候需要一个limit波尔类型

    判断的数来判断他们是否达到搜索的最大值,即我们就要判断limit在上一层是否已经到达1在这层是否到达最大值的时候。其实总而言之就是dfs

    对于位数上的暴力查找,然后用数组来存一下来减少一些不必要的查找。

    一般来说,模板如下,这里我们以hdu2092为例

    题解:我们就是从最高位开始dfs如果遇到了4就continue,如果前一位为6而遍历到这一为2时continue;最后用dp数组来存一下这时候的结果

    ​
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof a)
    using namespace std;
    const int INF = 0x3f3f3f3f;
    int dp[11][11][2][2];
    int len;
    string s,t;
    string s_mo;
    int dfs(int cur,int x,bool limit,bool g)//cur位数  x代表前一位的数字  limit代表是否到达上界  g代表前置是否为零 
    {
    	if(cur==len) return 1;
    	if(!limit&&dp[cur][x][limit][g]!=-1) return dp[cur][x][limit][g];
    	int v = 9;
    	if(limit)
    	{
    		v = s_mo[cur] - '0';
    	}
    	int ans = 0;
    	for(int i=0;i<=v;i++)
    	{
    		if(g==1)//前导为0的情况下 
    		{
    			if(i==0)
    			{
    				ans+=dfs(cur+1,0,limit&&i==v,1);
    			}
    			else if(i==4){
    				continue;
    			}
    			else{
    				ans+=dfs(cur+1,i,limit&&i==v,0);
    			}
    		}
    		else{//前导不为0的情况下 
    			if((x==6&&i==2)||i==4) continue;
    		    else{
    			    ans+=dfs(cur+1,i,limit&&i==v,0);
    		    }
    		}
    	}
    	return dp[cur][x][limit][g] = ans;
    }
    int solve(string ss)
    {
    	mem(dp,-1);
    	len = ss.size();
    	s_mo = ss;
    	return dfs(0,0,1,1);
    	
    }
    bool chk(string ss)
    {
    	bool flag = 0;
    	for(int i=0;i<ss.length();i++)
    	{
    		if(s[i]=='4') flag = 1;
    		else if(s[i]=='6'&&s[i+1]=='2'){
    			flag = 1;
    		}
    	}
    	return 1-flag ;
    }
    int main()
    {
        int n,m;
        while(cin>>s>>t)//输入字符串类型有利于从最高位开始遍历 
        {
        	if(s=="0"&&t=="0") break;
        	int ans = solve(t) -solve(s) + chk(s);
        	cout<<ans<<endl;
    	}
        return 0;
    }
     
    ​
    

      

  • 相关阅读:
    Winform使用ML.NET时无法加载 DLL“CpuMathNative”问题的解决方法
    离线安装nuget包EPPlus
    码云上webide怎么提交
    EXCEL中自定义格式输入的数据怎么完整复制
    远程桌面剪贴板不好用了
    电脑里明明安装了net4.7但是VS里不显示?
    微信公众号里的音频怎么下载
    Hibernate-ORM:06.Hibernate中三种状态
    Hibernate-ORM:05.Hibernate中的list()和iterator()
    Hibernate-ORM:04.Hibernate中的get()和load()
  • 原文地址:https://www.cnblogs.com/lcsdsg/p/14340723.html
Copyright © 2011-2022 走看看