bzoj 1026 //1026: [SCOI2009]windy数

bzoj 1026 //1026: [SCOI2009]windy数   //在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=1026
//在线测评地址https://www.luogu.org/problem/P2657

更多题解,详见https://blog.csdn.net/mrcrack/article/details/90228694BZOJ刷题记录

方法一:数位dp 模板 记忆化搜索

Accepted 824 kb 60 ms C++/Edit 1086 B

//1026: [SCOI2009]windy数
//在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=1026
//在线测评地址https://www.luogu.org/problem/P2657
//看了数据范围 1 <= A <= B <= 2000000000 ,long long比较稳妥
//枚举算法容易编写,AC不了,是肯定的。2019-11-9 19:44
//先解决样例
//编写完枚举算法,测试了样例,才发现没有读懂题意,什么是windy数,要是题目能举例说明就好了。
//样例2,很快弄懂,
/*
25~31共7个
35~42共8个
46~50共5个
7+8+5=20个
*/
//样例1,始终没弄懂。
//在想,要么样例1,就是作为特例给出,1-9之间9个数,都是特殊的windy数.2019-11-9 20:08
//数位dp入门,此文https://www.luogu.org/blog/virus2017/shuweidp可以读读。2019-11-10 18:43
//此文https://www.luogu.org/problemnew/solution/P2657   作者: Mathison 更新时间: 2018-09-27 16:25代码写得不错
//凭着记忆,硬写,错误不断,不过,也就逐渐有了感觉。
//样例通过,提交AC.2019-11-12 20:42
#include
#include
#define LL long long
int L,R;
LL ans,dp[15][15];
int a[15],len;
int myabs(int x){
    return x>=0?x:-x;
}
LL dfs(int pos,int pre,int lead,int limit){
    LL ret=0;
    int res,i;
    if(pos>len)return 1;//此处错写成if(pos     if(!limit&&dp[pos][pre]!=-1)return dp[pos][pre];
    res=limit?a[len-pos+1]:9;//此处错写成res=limit?a[len-pos-1]:9;
    for(i=0;i<=res;i++){
        if(myabs(i-pre)<2)continue;
        if(lead&&!i)ret+=dfs(pos+1,-2,1,limit&&i==res);//前导0
        else ret+=dfs(pos+1,i,0,limit&&i==res);//此处错写成if(!lead)ret+=dfs(pos+1,i,0,limit&&i==res);
    }
    if(!limit&&!lead)dp[pos][pre]=ret;//此处错写成if(!limit&&!lead)ret=dp[pos][pre];
    return ret;
}
void part(int x){
    ans=0,len=0;
    while(x)a[++len]=x%10,x/=10;
    memset(dp,-1,sizeof(dp));
    ans=dfs(1,-2,1,1);
}
int main(){
    LL mx,mn;
    scanf("%d%d",&L,&R);
    part(L-1),mn=ans;
    part(R),mx=ans;
    printf("%lld\n",mx-mn);
    return 0;
}

你可能感兴趣的:(跟着大佬学算法)