bzoj 1026 [ SCOI2009 ] windy数 —— 数位DP

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1026

蛮简单的数位DP,预处理 f[i][j] 表示 i 位数,以 j 开头的 windy 数个数;

但不明白为什么最后一位拿出来特判 ret++  不对,而写在循环里,特判 i==1 就对了...

代码如下:

复制代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a,b,f[15][15],num[15];
int abb(int x){return (x>0)?x:-x;}
int getnum(int x)
{
    int cnt=0;
    while(x)num[++cnt]=x%10,x/=10;
    return cnt;
}
void init()
{
    int mx=getnum(b);
    for(int i=0;i<=9;i++)f[1][i]=1;
    for(int i=2;i<=mx;i++)
        for(int j=0;j<=9;j++)
            for(int k=0;k<=9;k++)    
                if(abb(j-k)>=2)f[i][j]+=f[i-1][k];
}
int calc(int x)
{
    int mx=getnum(x),ret=0;
    for(int i=1;i<mx;i++)
        for(int j=1;j<=9;j++)ret+=f[i][j];
    for(int j=1;j<num[mx];j++)ret+=f[mx][j];
    for(int i=mx-1,pre;i;i--)
    {
        pre=num[i+1];
        if(i!=1)
        {
            for(int j=0;j<num[i];j++)
                if(abb(pre-j)>=2)ret+=f[i][j];
        }
        if(i==1)//AC
        {
            for(int j=0;j<=num[i];j++)
                if(abb(pre-j)>=2)ret+=f[i][j];
        }
        if(abb(num[i]-pre)<2)break;//!
    }
//    if(mx==1||abb(num[1]-num[2])>=2)ret++;//WA
//    if(abb(num[1]-num[2])>=2)ret++;//WA
    return ret;
}
int main()
{
    scanf("%d%d",&a,&b);
    init();
    printf("%d\n",calc(b)-calc(a-1));
    return 0;
}
复制代码

 

posted @   Zinn  阅读(181)  评论(0编辑  收藏  举报
编辑推荐:
· 你所不知道的 C/C++ 宏知识
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· SQL Server 内存占用高分析
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
阅读排行:
· 我干了两个月的大项目,开源了!
· 推荐一款非常好用的在线 SSH 管理工具
· 千万级的大表,如何做性能调优?
· 盘点!HelloGitHub 年度热门开源项目
· Phi小模型开发教程:用C#开发本地部署AI聊天工具,只需CPU,不需要GPU,3G内存就可以运行,
点击右上角即可分享
微信分享提示