洛谷P2657 [SCOI2009]windy数 [数位DP,记忆化搜索]

  题目传送门

windy数

题目描述

windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,

在A和B之间,包括A和B,总共有多少个windy数?

输入输出格式

输入格式:

 

包含两个整数,A B。

 

输出格式:

 

一个整数

 

输入输出样例

输入样例#1: 
1 10
输出样例#1: 
9
输入样例#2: 
25 50
输出样例#2: 
20

说明

100%的数据,满足 1 <= A <= B <= 2000000000 。


  分析:

  据大佬说这是一道数位DP模板???我DP不好别骗我QWQ。。。

  好吧,一开始打了个暴搜看能水多少,可能我写挂了只拿10分QAQ???然后打了一下正解记忆化搜索,貌似真是一个数位DP模板???看来还是我太菜了。。。

  这道题需要注意的就是当前搜索的情况如果是前导零或者顶端情况的时候需要特判,所以在搜索的时候加入两个bool变量判断一下,剩下的貌似真就是一个模板了。。。

  Code:

//It is made by HolseLee on 22rd July 2018
//Luogu.org P2657
#include<bits/stdc++.h>
using namespace std;
int num[11],dp[11][11];
inline int read()
{
  char ch=getchar();int num=0;
  while(ch<'0'||ch>'9')ch=getchar();
  while(ch>='0'&&ch<='9'){
    num=num*10+ch-'0';ch=getchar();}
  return num;
}
inline int Abs(int x)
{
  return x>0?x:-x;
}
inline int dfs(int len,int las,bool top,bool zero)
{
  if(len==0)return 1;
  if(!top&&!zero&&dp[len][las]!=-1)
    return dp[len][las];
  int cnt=0,maxx=(top?num[len]:9);
  for(int i=0;i<=maxx;i++){
    if(Abs(i-las)<2)continue;
    int p=i;if(zero&&i==0)p=-555;
    cnt+=dfs(len-1,p,top&&(i==maxx),(p==-555));
  }
  if(!zero&&!top)dp[len][las]=cnt;
  return cnt;
}
inline int work(int x)
{
  int tot=0;
  while(x){num[++tot]=x%10;x/=10;}
  memset(dp,-1,sizeof(dp));
  return dfs(tot,-555,true,true);
}
int main()
{
  int x=read();int y=read();
  printf("%d",work(y)-work(x-1));
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/cytus/p/9351033.html